Merge bk://linuxusb.bkbits.net/linus-2.5
into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
diff --git a/CREDITS b/CREDITS
index 7ac7107..5bc325b 100644
--- a/CREDITS
+++ b/CREDITS
@@ -2133,7 +2133,7 @@
 S: Germany
 
 N: Thomas Molina
-E: tmolina@home.com
+E: tmolina@cox.net
 D: bug fixes, documentation, minor hackery
 
 N: David Mosberger-Tang
@@ -2537,6 +2537,7 @@
 
 N: Thiago Berlitz Rondon
 E: maluco@mileniumnet.com.br
+W: http://vivaldi.linuxms.com.br/~maluco
 D: Miscellaneous kernel hacker
 S: R. Anhanguera, 1487 - Ipiranga
 S: 79080-740 - Campo Grande - Mato Grosso do Sul
@@ -3289,9 +3290,10 @@
 S: USA
 
 N: Richard Zidlicky
-E: rdzidlic@geocities.com,rdzidlic@cip.informatik.uni-erlangen.de
-W: http://www.geocities.com/SiliconValley/Bay/2602/
+E: rz@linux-m68k.org, rdzidlic@geocities.com
+W: http://www.geocities.com/rdzidlic
 D: Q40 port - see arch/m68k/q40/README
+D: various m68k hacks
 S: Germany
 
 N: Werner Zimmermann
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
index ec202d8..96cd716 100644
--- a/Documentation/00-INDEX
+++ b/Documentation/00-INDEX
@@ -12,14 +12,14 @@
 
 00-INDEX
 	- this file.
+BK-usage/
+	- directory with info on BitKeeper.
 BUG-HUNTING
 	- brute force method of doing binary search of patches to find bug.
 Changes
 	- list of changes that break older software packages.
 CodingStyle
 	- how the boss likes the C code in the kernel to look.
-Configure.help
-	- text file that is used for help when you run "make config"
 DMA-mapping.txt
 	- info for PCI drivers using DMA portably across all platforms.
 DocBook/
@@ -34,6 +34,10 @@
 	- info on Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux
 README.moxa
 	- release notes for Moxa mutiport serial card.
+README.nsp_cs.eng
+	- info on WorkBiT NinjaSCSI-3/32Bi driver.
+SAK.txt
+	- info on Secure Attention Keys.
 SubmittingDrivers
 	- procedure to get a new driver source included into the kernel tree.
 SubmittingPatches
@@ -44,6 +48,8 @@
 	- directory with info about Linux on the ARM architecture.
 binfmt_misc.txt
 	- info on the kernel support for extra binary formats.
+block/
+	- info on the Block I/O (BIO) layer.
 cachetlb.txt
 	- describes the cache/TLB flushing interfaces Linux uses.
 cciss.txt
@@ -54,6 +60,8 @@
 	- info on Computone Intelliport II/Plus Multiport Serial Driver
 cpqarray.txt
 	- info on using Compaq's SMART2 Intelligent Disk Array Controllers.
+cris/
+	- directory with info about Linux on CRIS architecture.
 devices.txt
 	- plain ASCII listing of all the nodes in /dev/ with major minor #'s
 digiboard.txt
@@ -62,6 +70,8 @@
 	- info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards.
 dnotify.txt
 	- info about directory notification in Linux.
+driver-model.txt
+	- info about Linux driver model.
 exception.txt
 	- how Linux v2.2 handles exceptions without verify_area etc.
 fb/
@@ -80,12 +90,16 @@
 	- directory with info about the I2C bus/protocol (2 wire, kHz speed)
 i386/
 	- directory with info about Linux on intel 32 bit architecture.
+i810_rng.txt
+	- info on Linux support for random number generator in i8xx chipsets.
 ia64/
 	- directory with info about Linux on intel 64 bit architecture.
 ide.txt
 	- important info for users of ATA devices (IDE/EIDE disks and CD-ROMS)
 initrd.txt
 	- how to use the RAM disk as an initial/temporary root filesystem.
+input/
+	- info on Linux input device support.
 ioctl-number.txt
 	- how to implement and register device/driver ioctl calls.
 isapnp.txt
@@ -94,12 +108,6 @@
 	- directory with info on the Linux ISDN support, and supported cards.
 java.txt
 	- info on the in-kernel binary support for Java(tm)
-joystick-api.txt
-	- API specification for applications that will be using the joystick.
-joystick-parport.txt 
-	- info on how to hook joysticks/gamepads to the parallel port.
-joystick.txt
-	- info on using joystick devices (and driver) with Linux.
 kbuild/
 	- directory with info about the kernel build process
 kernel-doc-nano-HOWTO.txt
@@ -128,6 +136,8 @@
 	- info on boot arguments for the multiple devices driver
 memory.txt
 	- info on typical Linux memory problems.
+mips/
+	- directory with info about Linux on MIPS architecture.
 mkdev.cciss
 	- script to make /dev entries for SMART controllers (see cciss.txt)
 mkdev.ida
@@ -161,9 +171,13 @@
 pcwd-watchdog.txt
 	- info and sample code for using with the PC Watchdog reset card.
 pm.txt
-	- info on Linux power management support
+	- info on Linux power management support.
+power/
+	- directory with info on Linux PCI power management.
 powerpc/
 	- directory with info on using Linux with the PowerPC.
+preempt-locking.txt
+	- info on locking under a preemptive kernel.
 ramdisk.txt
 	- short guide on how to set up and use the RAM disk.
 riscom8.txt
@@ -172,6 +186,8 @@
 	- notes on how to use the Real Time Clock (aka CMOS clock) driver.
 s390/
 	- directory with info on using Linux on the IBM S390.
+sh/
+	- directory with info on porting Linux to a new architecture.
 scsi-generic.txt
 	- info on the sg driver for generic (non-disk/CD/tape) SCSI devices.
 scsi.txt
@@ -186,6 +202,8 @@
 	- LaTeX document describing implementation of Multiprocessor Linux
 smp.txt
 	- a few more notes on symmetric multi-processing
+sonypi.txt
+	- info on Linux Sony Programmable I/O Device support.
 sound/
 	- directory with info on sound card support
 sparc/
@@ -216,6 +234,8 @@
 	- directory with info on the Linux vm code.
 watchdog.txt
 	- how to auto-reboot Linux if it has "fallen and can't get up". ;-)
+x86_64/
+	- directory with info on Linux support for AMD x86-64 (Hammer) machines.
 xterm-linux.xpm
 	- XPM image of penguin logo (see logo.txt) sitting on an xterm.
 zorro.txt
diff --git a/Documentation/BK-usage/bksend b/Documentation/BK-usage/bksend
new file mode 100755
index 0000000..dbeeefa
--- /dev/null
+++ b/Documentation/BK-usage/bksend
@@ -0,0 +1,36 @@
+#!/bin/sh
+# A script to format BK changeset output in a manner that is easy to read.
+# Andreas Dilger <adilger@turbolabs.com>  13/02/2002
+#
+# Add diffstat output after Changelog <adilger@turbolabs.com>   21/02/2002
+
+PROG=bksend
+
+usage() {
+	echo "usage: $PROG -r<rev>"
+	echo -e "\twhere <rev> is of the form '1.23', '1.23..', '1.23..1.27',"
+	echo -e "\tor '+' to indicate the most recent revision"
+
+	exit 1
+}
+
+case $1 in
+-r) REV=$2; shift ;;
+-r*) REV=`echo $1 | sed 's/^-r//'` ;;
+*) echo "$PROG: no revision given, you probably don't want that";;
+esac
+
+[ -z "$REV" ] && usage
+
+echo "You can import this changeset into BK by piping this whole message to:"
+echo "'| bk receive [path to repository]' or apply the patch as usual."
+
+SEP="\n===================================================================\n\n"
+echo -e $SEP
+bk changes -r$REV
+echo
+bk export -tpatch -du -h -r$REV | diffstat
+echo; echo
+bk export -tpatch -du -h -r$REV
+echo -e $SEP
+bk send -wgzip_uu -r$REV -
diff --git a/Documentation/BK-usage/bz64wrap b/Documentation/BK-usage/bz64wrap
new file mode 100755
index 0000000..be78087
--- /dev/null
+++ b/Documentation/BK-usage/bz64wrap
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+# bz64wrap - the sending side of a bzip2 | base64 stream
+# Andreas Dilger <adilger@clusterfs.com>   Jan 2002
+
+
+PATH=$PATH:/usr/bin:/usr/local/bin:/usr/freeware/bin
+
+# A program to generate base64 encoding on stdout
+BASE64_ENCODE="uuencode -m /dev/stdout"
+BASE64_BEGIN=
+BASE64_END=
+
+BZIP=NO
+BASE64=NO
+
+# Test if we have the bzip program installed
+bzip2 -c /dev/null > /dev/null 2>&1 && BZIP=YES
+
+# Test if uuencode can handle the -m (MIME) encoding option
+$BASE64_ENCODE < /dev/null > /dev/null 2>&1 && BASE64=YES
+
+if [ $BASE64 = NO ]; then
+	BASE64_ENCODE=mimencode
+	BASE64_BEGIN="begin-base64 644 -"
+	BASE64_END="===="
+
+	$BASE64_ENCODE < /dev/null > /dev/null 2>&1 && BASE64=YES
+fi
+
+if [ $BZIP = NO -o $BASE64 = NO ]; then
+	echo "$0: can't use bz64 encoding: bzip2=$BZIP, $BASE64_ENCODE=$BASE64"
+	exit 1
+fi
+
+# Sadly, mimencode does not appear to have good "begin" and "end" markers
+# like uuencode does, and it is picky about getting the right start/end of
+# the base64 stream, so we handle this internally.
+echo "$BASE64_BEGIN"
+bzip2 -9 | $BASE64_ENCODE
+echo "$BASE64_END"
diff --git a/Documentation/BK-usage/cset-to-linus b/Documentation/BK-usage/cset-to-linus
index ae03b2c..d28a96f 100755
--- a/Documentation/BK-usage/cset-to-linus
+++ b/Documentation/BK-usage/cset-to-linus
@@ -1,4 +1,4 @@
-#!/usr/bin/perl5.6.1 -w
+#!/usr/bin/perl -w
 
 use strict;
 
diff --git a/Documentation/BK-usage/csets-to-patches b/Documentation/BK-usage/csets-to-patches
index 3e13509..e2b81c3 100755
--- a/Documentation/BK-usage/csets-to-patches
+++ b/Documentation/BK-usage/csets-to-patches
@@ -1,4 +1,4 @@
-#!/usr/bin/perl5.6.1 -w
+#!/usr/bin/perl -w
 
 use strict;
 
diff --git a/Documentation/BK-usage/unbz64wrap b/Documentation/BK-usage/unbz64wrap
new file mode 100755
index 0000000..ccef3dd
--- /dev/null
+++ b/Documentation/BK-usage/unbz64wrap
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# unbz64wrap - the receiving side of a bzip2 | base64 stream
+# Andreas Dilger <adilger@clusterfs.com>   Jan 2002
+
+# Sadly, mimencode does not appear to have good "begin" and "end" markers
+# like uuencode does, and it is picky about getting the right start/end of
+# the base64 stream, so we handle this explicitly here.
+
+PATH=$PATH:/usr/bin:/usr/local/bin:/usr/freeware/bin
+
+if mimencode -u < /dev/null > /dev/null 2>&1 ; then
+	SHOW=
+	while read LINE; do
+		case $LINE in
+		begin-base64*) SHOW=YES ;;
+		====) SHOW= ;;
+		*) [ "$SHOW" ] && echo $LINE ;;
+		esac
+	done | mimencode -u | bunzip2
+	exit $?
+else
+	cat - | uudecode -o /dev/stdout | bunzip2
+	exit $?
+fi
diff --git a/Documentation/Changes b/Documentation/Changes
index 8d7aea6..35bead6 100644
--- a/Documentation/Changes
+++ b/Documentation/Changes
@@ -55,7 +55,7 @@
 o  modutils               2.4.2                   # insmod -V
 o  e2fsprogs              1.25                    # tune2fs
 o  jfsutils               1.0.14                  # fsck.jfs -V
-o  reiserfsprogs          3.x.0j                  # reiserfsck 2>&1|grep reiserfsprogs
+o  reiserfsprogs          3.x.1b                  # reiserfsck 2>&1|grep reiserfsprogs
 o  pcmcia-cs              3.1.21                  # cardmgr -V
 o  PPP                    2.4.0                   # pppd --version
 o  isdn4k-utils           3.1pre1                 # isdnctrl 2>&1|grep version
@@ -107,8 +107,8 @@
 your kernel.  This change does, however, mean that you need a recent
 release of binutils.
 
-System utililities
-==================
+System utilities
+================
 
 Architectural changes
 ---------------------
@@ -320,7 +320,7 @@
 
 Reiserfsprogs
 -------------
-o  <ftp://ftp.namesys.com/pub/reiserfsprogs/reiserfsprogs-3.x.0j.tar.gz>
+o  <ftp://ftp.namesys.com/pub/reiserfsprogs/reiserfsprogs-3.x.0b.tar.gz>
 
 LVM toolset
 -----------
diff --git a/Documentation/DMA-mapping.txt b/Documentation/DMA-mapping.txt
index 1690b0e..d51adf4 100644
--- a/Documentation/DMA-mapping.txt
+++ b/Documentation/DMA-mapping.txt
@@ -759,13 +759,10 @@
    Struct scatterlist must contain, at a minimum, the following
    members:
 
-	char *address;
 	struct page *page;
 	unsigned int offset;
 	unsigned int length;
 
-   The "address" member will disappear in 2.5.x
-
    This means that your pci_{map,unmap}_sg() and all other
    interfaces dealing with scatterlists must be able to cope
    properly with page being non NULL.
@@ -775,9 +772,6 @@
    If "address" is NULL, then "page+offset" is being used.
    If "page" is NULL, then "address" is being used.
 
-   In 2.5.x, all scatterlists will use "page+offset".  But during
-   2.4.x we still have to support the old method.
-
 2) More to come...
 
 			   Closing
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index a564b85..c8f0c98 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -59,8 +59,8 @@
 	$(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/net/wan/z85230.c \
 		<z8530book.tmpl >z8530book.sgml
 
-via-audio.sgml: via-audio.tmpl $(TOPDIR)/drivers/sound/via82cxxx_audio.c
-	$(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/sound/via82cxxx_audio.c \
+via-audio.sgml: via-audio.tmpl $(TOPDIR)/sound/oss/via82cxxx_audio.c
+	$(TOPDIR)/scripts/docgen $(TOPDIR)/sound/oss/via82cxxx_audio.c \
 		<via-audio.tmpl >via-audio.sgml
 
 tulip-user.sgml: tulip-user.tmpl
@@ -100,8 +100,8 @@
 		$(TOPDIR)/drivers/hotplug/pci_hotplug_core.c \
 		$(TOPDIR)/drivers/hotplug/pci_hotplug_util.c \
 		$(TOPDIR)/drivers/block/ll_rw_blk.c \
-		$(TOPDIR)/drivers/sound/sound_core.c \
-		$(TOPDIR)/drivers/sound/sound_firmware.c \
+		$(TOPDIR)/sound/sound_core.c \
+		$(TOPDIR)/sound/sound_firmware.c \
 		$(TOPDIR)/drivers/net/wan/syncppp.c \
 		$(TOPDIR)/drivers/net/wan/z85230.c \
 		$(TOPDIR)/drivers/usb/hcd.c \
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 69bf709..8b70881 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -203,8 +203,8 @@
 
   <chapter id="snddev">
      <title>Sound Devices</title>
-!Edrivers/sound/sound_core.c
-!Idrivers/sound/sound_firmware.c
+!Esound/sound_core.c
+!Isound/sound_firmware.c
   </chapter>
 
   <chapter id="usb">
diff --git a/Documentation/DocBook/via-audio.tmpl b/Documentation/DocBook/via-audio.tmpl
index f06641a..0471cce 100644
--- a/Documentation/DocBook/via-audio.tmpl
+++ b/Documentation/DocBook/via-audio.tmpl
@@ -537,7 +537,7 @@
    </listitem>
    <listitem>
     <para>
- Optimize included headers to eliminate headers found in linux/drivers/sound
+ Optimize included headers to eliminate headers found in linux/sound
 	</para>
    </listitem>
   </itemizedlist>
@@ -587,7 +587,9 @@
   
   <chapter id="intfunctions">
      <title>Internal Functions</title>
-!Idrivers/sound/via82cxxx_audio.c
+!Isound/oss/via82cxxx_audio.c
   </chapter>
 
 </book>
+
+
diff --git a/Documentation/SubmittingDrivers b/Documentation/SubmittingDrivers
index 4588d36..72574d4 100644
--- a/Documentation/SubmittingDrivers
+++ b/Documentation/SubmittingDrivers
@@ -3,7 +3,7 @@
 
 This document is intended to explain how to submit device drivers to the
 Linux 2.2 and 2.4 kernel trees. Note that if you are interested in video
-card drivers you should probably talk to XFree86 (http://wwww.xfree86.org) 
+card drivers you should probably talk to XFree86 (http://www.xfree86.org) 
 instead.
 
 Also read the Documentation/SubmittingPatches document.
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 9d1a96f..08a52c4 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -140,6 +140,10 @@
 	int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
 	int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
 	int (*bmap)(struct address_space *, long);
+	int (*flushpage) (struct page *, unsigned long);
+	int (*releasepage) (struct page *, int);
+	int (*direct_IO)(int, struct inode *, struct kiobuf *, unsigned long, int);
+
 locking rules:
 	All may block
 		BKL	PageLocked(page)
@@ -149,6 +153,8 @@
 prepare_write:	no	yes
 commit_write:	no	yes
 bmap:		yes
+flushpage:	no	yes
+releasepage:	no	yes
 
 	->prepare_write(), ->commit_write(), ->sync_page() and ->readpage()
 may be called from the request handler (/dev/loop).
@@ -161,6 +167,15 @@
 filesystems and by the swapper. The latter will eventually go away. All
 instances do not actually need the BKL. Please, keep it that way and don't
 breed new callers.
+	->flushpage() is called when the filesystem must attempt to drop
+some or all of the buffers from the page when it is being truncated.  It
+returns zero on success.  If ->flushpage is zero, the kernel uses
+block_flushpage() instead.
+	->releasepage() is called when the kernel is about to try to drop the
+buffers from the page in preparation for freeing it.  It returns zero to
+indicate that the buffers are (or may be) freeable.  If ->releasepage is zero,
+the kernel assumes that the fs has no private interest in the buffers.
+
 	Note: currently almost all instances of address_space methods are
 using BKL for internal serialization and that's one of the worst sources
 of contention. Normally they are calling library functions (in fs/buffer.c)
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index b4ed0da..be8601c 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -17,6 +17,7 @@
 	CD	Appropriate CD support is enabled.
 	DEVFS   devfs support is enabled. 
 	DRM	Direct Rendering Management support is enabled. 
+	EFI	EFI Partitioning (GPT) is enabled
 	EIDE	EIDE/ATAPI support is enabled.
 	FB	The frame buffer device is enabled.
 	HW	Appropriate hardware is enabled.
@@ -219,6 +220,9 @@
  
 	gdth=		[HW,SCSI]
 
+	gpt             [EFI] Forces disk with valid GPT signature but
+			invalid Protective MBR to be treated as GPT.
+
 	gscd=		[HW,CD]
 
 	gus=		[HW,SOUND] 
diff --git a/Documentation/networking/dl2k.txt b/Documentation/networking/dl2k.txt
index 04b1803..dbcf694 100644
--- a/Documentation/networking/dl2k.txt
+++ b/Documentation/networking/dl2k.txt
@@ -1,7 +1,7 @@
 
     D-Link DL2000-based Gigabit Ethernet Adapter Installation
     for Linux
-    Jan 02, 2002
+    Jan 29, 2002
 
 Contents
 ========
@@ -199,8 +199,8 @@
 				  6          	1000Mbps full duplex.
 
 				  By default, the NIC operates at autosense.
-				  Note that only 1000mbps_fd and 1000mbps_hd
-				  types are available for fiber adapter.
+				  1000mbps_fd and 1000mbps_hd types are only
+				  available for fiber adapter.
 
 vlan=[0|1]			- Specifies the VLAN ID. If vlan=0, the
 				  Virtual Local Area Network (VLAN) function is
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index e0588af..2de4d27 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -126,7 +126,13 @@
 	if network conditions require more than default value.
 
 tcp_tw_recycle - BOOLEAN
-	Enable fast recycling TIME-WAIT sockets. Default value is 1.
+	Enable fast recycling TIME-WAIT sockets. Default value is 0.
+	It should not be changed without advice/request of technical
+	experts.
+
+tcp_tw_reuse - BOOLEAN
+	Allow to reuse TIME-WAIT sockets for new connections when it is
+	safe from protocol viewpoint. Default value is 0.
 	It should not be changed without advice/request of technical
 	experts.
 
@@ -182,10 +188,7 @@
 	still did not receive an acknowledgement from connecting client.
 	Default value is 1024 for systems with more than 128Mb of memory,
 	and 128 for low memory machines. If server suffers of overload,
-	try to increase this number. Warning! If you make it greater
-	than 1024, it would be better to change TCP_SYNQ_HSIZE in
-	include/net/tcp.h to keep TCP_SYNQ_HSIZE*16<=tcp_max_syn_backlog
-	and to recompile kernel.
+	try to increase this number.
 
 tcp_window_scaling - BOOLEAN
 	Enable window scaling as defined in RFC1323.
@@ -358,6 +361,17 @@
 	Do multicast routing. The kernel needs to be compiled with CONFIG_MROUTE
 	and a multicast routing daemon is required.
 
+medium_id - INTEGER
+	Integer value used to differentiate the devices by the medium they
+	are attached to. Two devices can have different id values when
+	the broadcast packets are received only on one of them.
+	The default value 0 means that the device is the only interface
+	to its medium, value of -1 means that medium is not known.
+	
+	Currently, it is used to change the proxy_arp behavior:
+	the proxy_arp feature is enabled for packets forwarded between
+	two devices attached to different media.
+
 proxy_arp - BOOLEAN
 	Do proxy arp.
 
diff --git a/Documentation/networking/ppp_generic.txt b/Documentation/networking/ppp_generic.txt
new file mode 100644
index 0000000..15b5172
--- /dev/null
+++ b/Documentation/networking/ppp_generic.txt
@@ -0,0 +1,432 @@
+		PPP Generic Driver and Channel Interface
+		----------------------------------------
+
+			    Paul Mackerras
+			   paulus@samba.org
+			      7 Feb 2002
+
+The generic PPP driver in linux-2.4 provides an implementation of the
+functionality which is of use in any PPP implementation, including:
+
+* the network interface unit (ppp0 etc.)
+* the interface to the networking code
+* PPP multilink: splitting datagrams between multiple links, and
+  ordering and combining received fragments
+* the interface to pppd, via a /dev/ppp character device
+* packet compression and decompression
+* TCP/IP header compression and decompression
+* detecting network traffic for demand dialling and for idle timeouts
+* simple packet filtering
+
+For sending and receiving PPP frames, the generic PPP driver calls on
+the services of PPP `channels'.  A PPP channel encapsulates a
+mechanism for transporting PPP frames from one machine to another.  A
+PPP channel implementation can be arbitrarily complex internally but
+has a very simple interface with the generic PPP code: it merely has
+to be able to send PPP frames, receive PPP frames, and optionally
+handle ioctl requests.  Currently there are PPP channel
+implementations for asynchronous serial ports, synchronous serial
+ports, and for PPP over ethernet.
+
+This architecture makes it possible to implement PPP multilink in a
+natural and straightforward way, by allowing more than one channel to
+be linked to each ppp network interface unit.  The generic layer is
+responsible for splitting datagrams on transmit and recombining them
+on receive.
+
+
+PPP channel API
+---------------
+
+See include/linux/ppp_channel.h for the declaration of the types and
+functions used to communicate between the generic PPP layer and PPP
+channels.
+
+Each channel has to provide two functions to the generic PPP layer,
+via the ppp_channel.ops pointer:
+
+* start_xmit() is called by the generic layer when it has a frame to
+  send.  The channel has the option of rejecting the frame for
+  flow-control reasons.  In this case, start_xmit() should return 0
+  and the channel should call the ppp_output_wakeup() function at a
+  later time when it can accept frames again, and the generic layer
+  will then attempt to retransmit the rejected frame(s).  If the frame
+  is accepted, the start_xmit() function should return 1.
+
+* ioctl() provides an interface which can be used by a user-space
+  program to control aspects of the channel's behaviour.  This
+  procedure will be called when a user-space program does an ioctl
+  system call on an instance of /dev/ppp which is bound to the
+  channel.  (Usually it would only be pppd which would do this.)
+
+The generic PPP layer provides seven functions to channels:
+
+* ppp_register_channel() is called when a channel has been created, to
+  notify the PPP generic layer of its presence.  For example, setting
+  a serial port to the PPPDISC line discipline causes the ppp_async
+  channel code to call this function.
+
+* ppp_unregister_channel() is called when a channel is to be
+  destroyed.  For example, the ppp_async channel code calls this when
+  a hangup is detected on the serial port.
+
+* ppp_output_wakeup() is called by a channel when it has previously
+  rejected a call to its start_xmit function, and can now accept more
+  packets.
+
+* ppp_input() is called by a channel when it has received a complete
+  PPP frame.
+
+* ppp_input_error() is called by a channel when it has detected that a
+  frame has been lost or dropped (for example, because of a FCS (frame
+  check sequence) error).
+
+* ppp_channel_index() returns the channel index assigned by the PPP
+  generic layer to this channel.  The channel should provide some way
+  (e.g. an ioctl) to transmit this back to user-space, as user-space
+  will need it to attach an instance of /dev/ppp to this channel.
+
+* ppp_unit_number() returns the unit number of the ppp network
+  interface to which this channel is connected, or -1 if the channel
+  is not connected.
+
+Connecting a channel to the ppp generic layer is initiated from the
+channel code, rather than from the generic layer.  The channel is
+expected to have some way for a user-level process to control it
+independently of the ppp generic layer.  For example, with the
+ppp_async channel, this is provided by the file descriptor to the
+serial port.
+
+Generally a user-level process will initialize the underlying
+communications medium and prepare it to do PPP.  For example, with an
+async tty, this can involve setting the tty speed and modes, issuing
+modem commands, and then going through some sort of dialog with the
+remote system to invoke PPP service there.  We refer to this process
+as `discovery'.  Then the user-level process tells the medium to
+become a PPP channel and register itself with the generic PPP layer.
+The channel then has to report the channel number assigned to it back
+to the user-level process.  From that point, the PPP negotiation code
+in the PPP daemon (pppd) can take over and perform the PPP
+negotiation, accessing the channel through the /dev/ppp interface.
+
+At the interface to the PPP generic layer, PPP frames are stored in
+skbuff structures and start with the two-byte PPP protocol number.
+The frame does *not* include the 0xff `address' byte or the 0x03
+`control' byte that are optionally used in async PPP.  Nor is there
+any escaping of control characters, nor are there any FCS or framing
+characters included.  That is all the responsibility of the channel
+code, if it is needed for the particular medium.  That is, the skbuffs
+presented to the start_xmit() function contain only the 2-byte
+protocol number and the data, and the skbuffs presented to ppp_input()
+must be in the same format.
+
+The channel must provide an instance of a ppp_channel struct to
+represent the channel.  The channel is free to use the `private' field
+however it wishes.  The channel should initialize the `mtu' and
+`hdrlen' fields before calling ppp_register_channel() and not change
+them until after ppp_unregister_channel() returns.  The `mtu' field
+represents the maximum size of the data part of the PPP frames, that
+is, it does not include the 2-byte protocol number.
+
+If the channel needs some headroom in the skbuffs presented to it for
+transmission (i.e., some space free in the skbuff data area before the
+start of the PPP frame), it should set the `hdrlen' field of the
+ppp_channel struct to the amount of headroom required.  The generic
+PPP layer will attempt to provide that much headroom but the channel
+should still check if there is sufficient headroom and copy the skbuff
+if there isn't.
+
+On the input side, channels should ideally provide at least 2 bytes of
+headroom in the skbuffs presented to ppp_input().  The generic PPP
+code does not require this but will be more efficient if this is done.
+
+
+Buffering and flow control
+--------------------------
+
+The generic PPP layer has been designed to minimize the amount of data
+that it buffers in the transmit direction.  It maintains a queue of
+transmit packets for the PPP unit (network interface device) plus a
+queue of transmit packets for each attached channel.  Normally the
+transmit queue for the unit will contain at most one packet; the
+exceptions are when pppd sends packets by writing to /dev/ppp, and
+when the core networking code calls the generic layer's start_xmit()
+function with the queue stopped, i.e. when the generic layer has
+called netif_stop_queue(), which only happens on a transmit timeout.
+The start_xmit function always accepts and queues the packet which it
+is asked to transmit.
+
+Transmit packets are dequeued from the PPP unit transmit queue and
+then subjected to TCP/IP header compression and packet compression
+(Deflate or BSD-Compress compression), as appropriate.  After this
+point the packets can no longer be reordered, as the decompression
+algorithms rely on receiving compressed packets in the same order that
+they were generated.
+
+If multilink is not in use, this packet is then passed to the attached
+channel's start_xmit() function.  If the channel refuses to take
+the packet, the generic layer saves it for later transmission.  The
+generic layer will call the channel's start_xmit() function again
+when the channel calls  ppp_output_wakeup() or when the core
+networking code calls the generic layer's start_xmit() function
+again.  The generic layer contains no timeout and retransmission
+logic; it relies on the core networking code for that.
+
+If multilink is in use, the generic layer divides the packet into one
+or more fragments and puts a multilink header on each fragment.  It
+decides how many fragments to use based on the length of the packet
+and the number of channels which are potentially able to accept a
+fragment at the moment.  A channel is potentially able to accept a
+fragment if it doesn't have any fragments currently queued up for it
+to transmit.  The channel may still refuse a fragment; in this case
+the fragment is queued up for the channel to transmit later.  This
+scheme has the effect that more fragments are given to higher-
+bandwidth channels.  It also means that under light load, the generic
+layer will tend to fragment large packets across all the channels,
+thus reducing latency, while under heavy load, packets will tend to be
+transmitted as single fragments, thus reducing the overhead of
+fragmentation.
+
+
+SMP safety
+----------
+
+The PPP generic layer has been designed to be SMP-safe.  Locks are
+used around accesses to the internal data structures where necessary
+to ensure their integrity.  As part of this, the generic layer
+requires that the channels adhere to certain requirements and in turn
+provides certain guarantees to the channels.  Essentially the channels
+are required to provide the appropriate locking on the ppp_channel
+structures that form the basis of the communication between the
+channel and the generic layer.  This is because the channel provides
+the storage for the ppp_channel structure, and so the channel is
+required to provide the guarantee that this storage exists and is
+valid at the appropriate times.
+
+The generic layer requires these guarantees from the channel:
+
+* The ppp_channel object must exist from the time that
+  ppp_register_channel() is called until after the call to
+  ppp_unregister_channel() returns.
+
+* No thread may be in a call to any of ppp_input(), ppp_input_error(),
+  ppp_output_wakeup(), ppp_channel_index() or ppp_unit_number() for a
+  channel at the time that ppp_unregister_channel() is called for that
+  channel.
+
+* ppp_register_channel() and ppp_unregister_channel() must be called
+  from process context, not interrupt or softirq/BH context.
+
+* The remaining generic layer functions may be called at softirq/BH
+  level but must not be called from a hardware interrupt handler.
+
+* The generic layer may call the channel start_xmit() function at
+  softirq/BH level but will not call it at interrupt level.  Thus the
+  start_xmit() function may not block.
+
+* The generic layer will only call the channel ioctl() function in
+  process context.
+
+The generic layer provides these guarantees to the channels:
+
+* The generic layer will not call the start_xmit() function for a
+  channel while any thread is already executing in that function for
+  that channel.
+
+* The generic layer will not call the ioctl() function for a channel
+  while any thread is already executing in that function for that
+  channel.
+
+* By the time a call to ppp_unregister_channel() returns, no thread
+  will be executing in a call from the generic layer to that channel's
+  start_xmit() or ioctl() function, and the generic layer will not
+  call either of those functions subsequently.
+
+
+Interface to pppd
+-----------------
+
+The PPP generic layer exports a character device interface called
+/dev/ppp.  This is used by pppd to control PPP interface units and
+channels.  Although there is only one /dev/ppp, each open instance of
+/dev/ppp acts independently and can be attached either to a PPP unit
+or a PPP channel.  This is achieved using the file->private_data field
+to point to a separate object for each open instance of /dev/ppp.  In
+this way an effect similar to Solaris' clone open is obtained,
+allowing us to control an arbitrary number of PPP interfaces and
+channels without having to fill up /dev with hundreds of device names.
+
+When /dev/ppp is opened, a new instance is created which is initially
+unattached.  Using an ioctl call, it can then be attached to an
+existing unit, attached to a newly-created unit, or attached to an
+existing channel.  An instance attached to a unit can be used to send
+and receive PPP control frames, using the read() and write() system
+calls, along with poll() if necessary.  Similarly, an instance
+attached to a channel can be used to send and receive PPP frames on
+that channel.
+
+In multilink terms, the unit represents the bundle, while the channels
+represent the individual physical links.  Thus, a PPP frame sent by a
+write to the unit (i.e., to an instance of /dev/ppp attached to the
+unit) will be subject to bundle-level compression and to fragmentation
+across the individual links (if multilink is in use).  In contrast, a
+PPP frame sent by a write to the channel will be sent as-is on that
+channel, without any multilink header.
+
+A channel is not initially attached to any unit.  In this state it can
+be used for PPP negotiation but not for the transfer of data packets.
+It can then be connected to a PPP unit with an ioctl call, which
+makes it available to send and receive data packets for that unit.
+
+The ioctl calls which are available on an instance of /dev/ppp depend
+on whether it is unattached, attached to a PPP interface, or attached
+to a PPP channel.  The ioctl calls which are available on an
+unattached instance are:
+
+* PPPIOCNEWUNIT creates a new PPP interface and makes this /dev/ppp
+  instance the "owner" of the interface.  The argument should point to
+  an int which is the desired unit number if >= 0, or -1 to assign the
+  lowest unused unit number.  Being the owner of the interface means
+  that the interface will be shut down if this instance of /dev/ppp is
+  closed.
+
+* PPPIOCATTACH attaches this instance to an existing PPP interface.
+  The argument should point to an int containing the unit number.
+  This does not make this instance the owner of the PPP interface.
+
+* PPPIOCATTCHAN attaches this instance to an existing PPP channel.
+  The argument should point to an int containing the channel number.
+
+The ioctl calls available on an instance of /dev/ppp attached to a
+channel are:
+
+* PPPIOCDETACH detaches the instance from the channel.  This ioctl is
+  deprecated since the same effect can be achieved by closing the
+  instance.  In order to prevent possible races this ioctl will fail
+  with an EINVAL error if more than one file descriptor refers to this
+  instance (i.e. as a result of dup(), dup2() or fork()).
+
+* PPPIOCCONNECT connects this channel to a PPP interface.  The
+  argument should point to an int containing the interface unit
+  number.  It will return an EINVAL error if the channel is already
+  connected to an interface, or ENXIO if the requested interface does
+  not exist.
+
+* PPPIOCDISCONN disconnects this channel from the PPP interface that
+  it is connected to.  It will return an EINVAL error if the channel
+  is not connected to an interface.
+
+* All other ioctl commands are passed to the channel ioctl() function.
+
+The ioctl calls that are available on an instance that is attached to
+an interface unit are:
+
+* PPPIOCSMRU sets the MRU (maximum receive unit) for the interface.
+  The argument should point to an int containing the new MRU value.
+
+* PPPIOCSFLAGS sets flags which control the operation of the
+  interface.  The argument should be a pointer to an int containing
+  the new flags value.  The bits in the flags value that can be set
+  are:
+	SC_COMP_TCP		enable transmit TCP header compression
+	SC_NO_TCP_CCID		disable connection-id compression for
+				TCP header compression
+	SC_REJ_COMP_TCP		disable receive TCP header decompression
+	SC_CCP_OPEN		Compression Control Protocol (CCP) is
+				open, so inspect CCP packets
+	SC_CCP_UP		CCP is up, may (de)compress packets
+	SC_LOOP_TRAFFIC		send IP traffic to pppd
+	SC_MULTILINK		enable PPP multilink fragmentation on
+				transmitted packets
+	SC_MP_SHORTSEQ		expect short multilink sequence
+				numbers on received multilink fragments
+	SC_MP_XSHORTSEQ		transmit short multilink sequence nos.
+
+  The values of these flags are defined in <linux/if_ppp.h>.  Note
+  that the values of the SC_MULTILINK, SC_MP_SHORTSEQ and
+  SC_MP_XSHORTSEQ bits are ignored if the CONFIG_PPP_MULTILINK option
+  is not selected.
+
+* PPPIOCGFLAGS returns the value of the status/control flags for the
+  interface unit.  The argument should point to an int where the ioctl
+  will store the flags value.  As well as the values listed above for
+  PPPIOCSFLAGS, the following bits may be set in the returned value:
+	SC_COMP_RUN		CCP compressor is running
+	SC_DECOMP_RUN		CCP decompressor is running
+	SC_DC_ERROR		CCP decompressor detected non-fatal error
+	SC_DC_FERROR		CCP decompressor detected fatal error
+
+* PPPIOCSCOMPRESS sets the parameters for packet compression or
+  decompression.  The argument should point to a ppp_option_data
+  structure (defined in <linux/if_ppp.h>), which contains a
+  pointer/length pair which should describe a block of memory
+  containing a CCP option specifying a compression method and its
+  parameters.  The ppp_option_data struct also contains a `transmit'
+  field.  If this is 0, the ioctl will affect the receive path,
+  otherwise the transmit path.
+
+* PPPIOCGUNIT returns, in the int pointed to by the argument, the unit
+  number of this interface unit.
+
+* PPPIOCSDEBUG sets the debug flags for the interface to the value in
+  the int pointed to by the argument.  Only the least significant bit
+  is used; if this is 1 the generic layer will print some debug
+  messages during its operation.  This is only intended for debugging
+  the generic PPP layer code; it is generally not helpful for working
+  out why a PPP connection is failing.
+
+* PPPIOCGDEBUG returns the debug flags for the interface in the int
+  pointed to by the argument.
+
+* PPPIOCGIDLE returns the time, in seconds, since the last data
+  packets were sent and received.  The argument should point to a
+  ppp_idle structure (defined in <linux/ppp_defs.h>).  If the
+  CONFIG_PPP_FILTER option is enabled, the set of packets which reset
+  the transmit and receive idle timers is restricted to those which
+  pass the `active' packet filter.
+
+* PPPIOCSMAXCID sets the maximum connection-ID parameter (and thus the
+  number of connection slots) for the TCP header compressor and
+  decompressor.  The lower 16 bits of the int pointed to by the
+  argument specify the maximum connection-ID for the compressor.  If
+  the upper 16 bits of that int are non-zero, they specify the maximum
+  connection-ID for the decompressor, otherwise the decompressor's
+  maximum connection-ID is set to 15.
+
+* PPPIOCSNPMODE sets the network-protocol mode for a given network
+  protocol.  The argument should point to an npioctl struct (defined
+  in <linux/if_ppp.h>).  The `protocol' field gives the PPP protocol
+  number for the protocol to be affected, and the `mode' field
+  specifies what to do with packets for that protocol:
+
+	NPMODE_PASS	normal operation, transmit and receive packets
+	NPMODE_DROP	silently drop packets for this protocol
+	NPMODE_ERROR	drop packets and return an error on transmit
+	NPMODE_QUEUE	queue up packets for transmit, drop received
+			packets
+
+  At present NPMODE_ERROR and NPMODE_QUEUE have the same effect as
+  NPMODE_DROP.
+
+* PPPIOCGNPMODE returns the network-protocol mode for a given
+  protocol.  The argument should point to an npioctl struct with the
+  `protocol' field set to the PPP protocol number for the protocol of
+  interest.  On return the `mode' field will be set to the network-
+  protocol mode for that protocol.
+
+* PPPIOCSPASS and PPPIOCSACTIVE set the `pass' and `active' packet
+  filters.  These ioctls are only available if the CONFIG_PPP_FILTER
+  option is selected.  The argument should point to a sock_fprog
+  structure (defined in <linux/filter.h>) containing the compiled BPF
+  instructions for the filter.  Packets are dropped if they fail the
+  `pass' filter; otherwise, if they fail the `active' filter they are
+  passed but they do not reset the transmit or receive idle timer.
+
+* PPPIOCSMRRU enables or disables multilink processing for received
+  packets and sets the multilink MRRU (maximum reconstructed receive
+  unit).  The argument should point to an int containing the new MRRU
+  value.  If the MRRU value is 0, processing of received multilink
+  fragments is disabled.  This ioctl is only available if the
+  CONFIG_PPP_MULTILINK option is selected.
+
+Last modified: 7-feb-2002
diff --git a/Documentation/sonypi.txt b/Documentation/sonypi.txt
index 24d391c..4d5a8c6 100644
--- a/Documentation/sonypi.txt
+++ b/Documentation/sonypi.txt
@@ -25,7 +25,8 @@
 can be downloaded at: <http://www.alcove-labs.org/en/software/sonypi/>
 
 This driver supports also some ioctl commands for setting the LCD screen
-brightness (some more commands may be added in the future).
+brightness and querying the batteries charge information (some more 
+commands may be added in the future).
 
 This driver can also be used to set the camera controls on Picturebook series
 (brightness, contrast etc), and is used by the video4linux driver for the 
diff --git a/Documentation/sound/oss/AudioExcelDSP16 b/Documentation/sound/oss/AudioExcelDSP16
index f4ffd9d..d6130d9 100644
--- a/Documentation/sound/oss/AudioExcelDSP16
+++ b/Documentation/sound/oss/AudioExcelDSP16
@@ -2,7 +2,7 @@
 ------
 
 Informations about Audio Excel DSP 16 driver can be found in the source
-file lowlevel/aedsp16.c
+file aedsp16.c
 Please, read the head of the source before using it. It contain useful
 informations.
 
diff --git a/Documentation/usb/se401.txt b/Documentation/usb/se401.txt
index 46c9bc5..7b9d1c9 100644
--- a/Documentation/usb/se401.txt
+++ b/Documentation/usb/se401.txt
@@ -40,7 +40,7 @@
 KNOWN PROBLEMS:
 
 The driver works fine with the usb-ohci and uhci host controller drivers,
-the default settings also work with usb-uhci. But sending more then one bulk
+the default settings also work with usb-uhci. But sending more than one bulk
 transfer at a time with usb-uhci doesn't work yet.
 Users of usb-ohci and uhci can safely enlarge SE401_NUMSBUF in se401.h in
 order to increase the throughput (and thus framerate).
diff --git a/Documentation/video4linux/Zoran b/Documentation/video4linux/Zoran
index 67d87ff..e1dda3e 100644
--- a/Documentation/video4linux/Zoran
+++ b/Documentation/video4linux/Zoran
@@ -160,9 +160,9 @@
   set aside the necessary memory during boot time. There seem to be
   several versions of this patch against various kernel versions
   floating around in the net, you may obtain one e.g. from:
-  http://www.polyware.nl/~middelin/patch/bigphysarea-2.2.1.tar.gz You
-  also have to compile your driver AFTER installing that patch in order
-  to get it working
+  http://www.polyware.nl/~middelin/hob-v4l.html#bigphysarea
+  You also have to compile your driver AFTER installing that patch in
+  order to get it working
 
   or
 
diff --git a/Documentation/video4linux/bttv/README.freeze b/Documentation/video4linux/bttv/README.freeze
index 55642fa..968a5c3 100644
--- a/Documentation/video4linux/bttv/README.freeze
+++ b/Documentation/video4linux/bttv/README.freeze
@@ -46,10 +46,6 @@
 the PCI bus. The bt848/878 chips have a few workarounds for known
 incompatibilities, see README.quirks.
 
-Some folks report that increasing the pci latency helps too,
-althrought I'm not sure whenever this really fixes the problems or
-only makes it less likely to happen.
-
 Some mainboard have problems to deal correctly with multiple devices
 doing DMA at the same time.  bttv + ide seems to cause this sometimes,
 if this is the case you likely see freezes only with video and hard disk
diff --git a/Documentation/video4linux/w9966.txt b/Documentation/video4linux/w9966.txt
index d132c43..e7ac33a 100644
--- a/Documentation/video4linux/w9966.txt
+++ b/Documentation/video4linux/w9966.txt
@@ -1,37 +1,33 @@
+W9966 Camera driver, written by Jakob Kemi (jakob.kemi@telia.com)
 
-W9966 Camera driver, written by Jakob Kemi (jakob.kemi@post.utfors.se)
+After a lot of work in softice & wdasm, reading .pdf-files and tiresome
+trial-and-error work I've finally got everything to work. I needed vision for a
+robotics project so I borrowed this camera from a friend and started hacking.
+Anyway I've converted my original code from the AVR 8bit RISC C/ASM code into
+a working Linux driver.
 
-Ok, after a lot of work in softice, wdasm, reading pdf-files
-and trial-and-error work I've finally got everything to work.
-Since I needed some vision for a robotics project I borrowed
-this camera from a friend and started hacking. Anyway I've
-converted my original code from the AVR 8bit RISC C/asm
-into a working linux driver. I would really appreciate _any_
-kind of feedback regarding this driver.
+To get it working simply configure your kernel to support
+parport, ieee1284, video4linux and w9966
 
-To get it working quickly configure your kernel
-to support parport, ieee1284, video4linux, experimental drivers
-and w9966
-
-If w9966 is statically linked it will perform aggressive probing
-for the camera. If built as a module you'll have more configuration options.
+If w9966 is statically linked it will always perform aggressive probing for
+the camera. If built as a module you'll have more configuration options.
 
 Options:
-modprobe w9966.o pardev=parport0(or whatever) parmode=0 (0=auto, 1=ecp, 2=epp)
- 
+ modprobe w9966.o pardev=parport0(or whatever) parmode=0 (0=auto, 1=ecp, 2=epp)
 voila!
 
 you can also type 'modinfo -p w9966.o' for option usage
 (or checkout w9966.c)
 
-I've only tested it with custom built testprograms
-(http://hem.fyristorg.com/mogul/w9966.html) and with gqcam.
-(you'll need to tweak the code to qcam a bit to make it work,
-dimensions and such)
+The only thing to keep in mind is that the image format is in Y-U-Y-V format
+where every two pixels take 4 bytes. In SDL (www.libsdl.org) this format
+is called VIDEO_PALETTE_YUV422 (16 bpp).
+
+A minimal test application (with source) is available from:
+  http://hem.fyristorg.com/mogul/w9966.html
 
 The slow framerate is due to missing DMA ECP read support in the 
 parport drivers. I might add working EPP support later.
 
 Good luck!
-
-    /Jakob
+    /Jakob Kemi
diff --git a/Documentation/watchdog-api.txt b/Documentation/watchdog-api.txt
new file mode 100644
index 0000000..ce180c3
--- /dev/null
+++ b/Documentation/watchdog-api.txt
@@ -0,0 +1,390 @@
+The Linux Watchdog driver API.
+
+Copyright 2002 Christer Weingel <wingel@nano-system.com>
+
+Some parts of this document are copied verbatim from the sbc60xxwdt
+driver which is (c) Copyright 2000 Jakob Oestergaard <jakob@ostenfeld.dk>
+
+This document describes the state of the Linux 2.4.18 kernel.
+
+Introduction:
+
+A Watchdog Timer (WDT) is a hardware circuit that can reset the
+computer system in case of a software fault.  You probably knew that
+already.
+
+Usually a userspace daemon will notify the kernel watchdog driver via the
+/dev/watchdog special device file that userspace is still alive, at
+regular intervals.  When such a notification occurs, the driver will
+usually tell the hardware watchdog that everything is in order, and
+that the watchdog should wait for yet another little while to reset
+the system.  If userspace fails (RAM error, kernel bug, whatever), the
+notifications cease to occur, and the hardware watchdog will reset the
+system (causing a reboot) after the timeout occurs.
+
+The Linux watchdog API is a rather AD hoc construction and different
+drivers implement different, and sometimes incompatible, parts of it.
+This file is an attempt to document the existing usage and allow
+future driver writers to use it as a reference.
+
+The simplest API:
+
+All drivers support the basic mode of operation, where the watchdog
+activates as soon as /dev/watchdog is opened and will reboot unless
+the watchdog is pinged within a certain time, this time is called the
+timeout or margin.  The simplest way to ping the watchdog is to write
+some data to the device.  So a very simple watchdog daemon would look
+like this:
+
+int main(int argc, const char *argv[]) {
+	int fd=open("/dev/watchdog",O_WRONLY);
+	if (fd==-1) {
+		perror("watchdog");
+		exit(1);
+	}
+	while(1) {
+		write(fd, "\0", 1);
+		sleep(10);
+	}
+}
+
+A more advanced driver could for example check that a HTTP server is
+still responding before doing the write call to ping the watchdog.
+
+When the device is closed, the watchdog is disabled.  This is not
+always such a good idea, since if there is a bug in the watchdog
+daemon and it crashes the system will not reboot.  Because of this,
+some of the drivers support the configuration option "Disable watchdog
+shutdown on close", CONFIG_WATCHDOG_NOWAYOUT.  If it is set to Y when
+compiling the kernel, there is no way of disabling the watchdog once
+it has been started.  So, if the watchdog dameon crashes, the system
+will reboot after the timeout has passed.
+
+Some other drivers will not disable the watchdog, unless a specific
+magic character 'V' has been sent /dev/watchdog just before closing
+the file.  If the userspace daemon closes the file without sending
+this special character, the driver will assume that the daemon (and
+userspace in general) died, and will stop pinging the watchdog without
+disabling it first.  This will then cause a reboot.
+
+The ioctl API:
+
+All conforming drivers also support an ioctl API.
+
+Pinging the watchdog using an ioctl:
+
+All drivers that have an ioctl interface support at least one ioctl,
+KEEPALIVE.  This ioctl does exactly the same thing as a write to the
+watchdog device, so the main loop in the above program could be
+replaced with:
+
+	while (1) {
+		ioctl(fd, WDIOC_KEEPALIVE, 0);
+		sleep(10);
+	}
+
+the argument to the ioctl is ignored.
+
+Setting and getting the timeout:
+
+For some drivers it is possible to modify the watchdog timeout on the
+fly with the SETTIMEOUT ioctl, those drivers have the WDIOF_SETTIMEOUT
+flag set in their option field.  The argument is an integer
+representing the timeout in seconds.  The driver returns the real
+timeout used in the same variable, and this timeout might differ from
+the requested one due to limitation of the hardware.
+
+    int timeout = 45;
+    ioctl(fd, WDIOC_SETTIMEOUT, &timeout);
+    printf("The timeout was set to %d seconds\n", timeout);
+
+This example might actually print "The timeout was set to 60 seconds"
+if the device has a granularity of minutes for its timeout.
+
+Starting with the Linux 2.4.18 kernel, it is possible to query the
+current timeout using the GETTIMEOUT ioctl.
+
+    ioctl(fd, WDIOC_GETTIMEOUT, &timeout);
+    printf("The timeout was is %d seconds\n", timeout);
+
+Envinronmental monitoring:
+
+All watchdog drivers are required return more information about the system,
+some do temperature, fan and power level monitoring, some can tell you
+the reason for the last reboot of the system.  The GETSUPPORT ioctl is
+available to ask what the device can do:
+
+	struct watchdog_info ident;
+	ioctl(fd, WDIOC_GETSUPPORT, &ident);
+
+the fields returned in the ident struct are:
+
+        identity		a string identifying the watchdog driver
+	firmware_version	the firmware version of the card if available
+	options			a flags describing what the device supports
+
+the options field can have the following bits set, and describes what
+kind of information that the GET_STATUS and GET_BOOT_STATUS ioctls can
+return.   [FIXME -- Is this correct?]
+
+	WDIOF_OVERHEAT		Reset due to CPU overheat
+
+The machine was last rebooted by the watchdog because the thermal limit was
+exceeded
+
+	WDIOF_FANFAULT		Fan failed
+
+A system fan monitored by the watchdog card has failed
+
+	WDIOF_EXTERN1		External relay 1
+
+External monitoring relay/source 1 was triggered. Controllers intended for
+real world applications include external monitoring pins that will trigger
+a reset.
+
+	WDIOF_EXTERN2		External relay 2
+
+External monitoring relay/source 2 was triggered
+
+	WDIOF_POWERUNDER	Power bad/power fault
+
+The machine is showing an undervoltage status
+
+	WDIOF_CARDRESET		Card previously reset the CPU
+
+The last reboot was caused by the watchdog card
+
+	WDIOF_POWEROVER		Power over voltage
+
+The machine is showing an overvoltage status. Note that if one level is
+under and one over both bits will be set - this may seem odd but makes
+sense.
+
+	WDIOF_KEEPALIVEPING	Keep alive ping reply
+
+The watchdog saw a keepalive ping since it was last queried.
+
+	WDIOF_SETTIMEOUT	Can set/get the timeout
+
+
+For those drivers that return any bits set in the option field, the
+GETSTATUS and GETBOOTSTATUS ioctls can be used to ask for the current
+status, and the status at the last reboot, respectively.  
+
+    int flags;
+    ioctl(fd, WDIOC_GETSTATUS, &flags);
+
+    or
+
+    ioctl(fd, WDIOC_GETBOOTSTATUS, &flags);
+
+Note that not all devices support these two calls, and some only
+support the GETBOOTSTATUS call.
+
+Some drivers can measure the temperature using the GETTEMP ioctl.  The
+returned value is the temperature in degrees farenheit.
+
+    int temperature;
+    ioctl(fd, WDIOC_GETTEMP, &temperature);
+
+Finally the SETOPTIONS ioctl can be used to control some aspects of
+the cards operation; right now the pcwd driver is the only one
+supporting thiss ioctl.
+
+    int options = 0;
+    ioctl(fd, WDIOC_SETOPTIONS, options);
+
+The following options are available:
+
+	WDIOS_DISABLECARD	Turn off the watchdog timer
+	WDIOS_ENABLECARD	Turn on the watchdog timer
+	WDIOS_TEMPPANIC		Kernel panic on temperature trip
+
+[FIXME -- better explanations]
+
+Implementations in the current drivers in the kernel tree:
+
+Here I have tried to summarize what the different drivers support and
+where they do strange things compared to the other drivers.
+
+acquirewdt.c -- Acquire Single Board Computer
+
+	This driver has a hardcoded timeout of 1 minute
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT
+
+	GETSUPPORT returns KEEPALIVEPING.  GETSTATUS will return 1 if
+	the device is open, 0 if not.  [FIXME -- isn't this rather
+	silly?  To be able to use the ioctl, the device must be open
+	and so GETSTATUS will always return 1].
+
+advantechwdt.c -- Advantech Single Board Computer
+
+	Timeout that defaults to 60 seconds, supports SETTIMEOUT.
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT
+
+	GETSUPPORT returns WDIOF_KEEPALIVEPING and WDIOF_SETTIMEOUT.
+	The GETSTATUS call returns if the device is open or not.
+	[FIXME -- silliness again?]
+	
+eurotechwdt.c -- Eurotech CPU-1220/1410
+
+	The timeout can be set using the SETTIMEOUT ioctl and defaults
+	to 60 seconds.
+
+	Also has a module parameter "ev", event type which controls
+	what should happen on a timeout, the string "int" or anything
+	else that causes a reboot.  [FIXME -- better description]
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT
+
+	GETSUPPORT returns CARDRESET and WDIOF_SETTIMEOUT but
+	GETSTATUS is not supported and GETBOOTSTATUS just returns 0.
+
+i810-tco.c -- Intel 810 chipset
+
+	Also has support for a lot of other i8x0 stuff, but the
+	watchdog is one of the things.
+
+	The timeout is set using the module parameter "i810_margin",
+	which is in steps of 0.6 seconds where 2<i810_margin<64.  The
+	driver supports the SETTIMEOUT ioctl.
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT.
+
+	GETSUPPORT returns WDIOF_SETTIMEOUT.  The GETSTATUS call
+	returns some kind of timer value which ist not compatible with
+	the other drivers.  GETBOOT status returns some kind of
+	hardware specific boot status.  [FIXME -- describe this]
+
+ib700wdt.c -- IB700 Single Board Computer
+
+	Default timeout of 30 seconds and the timeout is settable
+	using the SETTIMEOUT ioctl.  Note that only a few timeout
+	values are supported.
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT
+
+	GETSUPPORT returns WDIOF_KEEPALIVEPING and WDIOF_SETTIMEOUT.
+	The GETSTATUS call returns if the device is open or not.
+	[FIXME -- silliness again?]
+
+machzwd.c -- MachZ ZF-Logic
+
+	Hardcoded timeout of 10 seconds
+
+	Has a module parameter "action" that controls what happens
+	when the timeout runs out which can be 0 = RESET (default), 
+	1 = SMI, 2 = NMI, 3 = SCI.
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT and the the magic character
+	'V' close handling.
+
+	GETSUPPORT returns WDIOF_KEEPALIVEPING, and the GETSTATUS call
+	returns if the device is open or not.  [FIXME -- silliness
+	again?]
+
+mixcomwd.c -- MixCom Watchdog
+
+	[FIXME -- I'm unable to tell what the timeout is]
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT
+
+	GETSUPPORT returns WDIOF_KEEPALIVEPING, GETSTATUS returns if
+	the device is opened or not [FIXME -- I'm not really sure how
+	this works, there seems to be some magic connected to
+	CONFIG_WATCHDOG_NOWAYOUT]
+
+pcwd.c -- Berkshire PC Watchdog
+
+	Hardcoded timeout of 1.5 seconds
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT
+
+	GETSUPPORT returns WDIOF_OVERHEAT|WDIOF_CARDRESET and both
+	GETSTATUS and GETBOOTSTATUS return something useful.
+
+	The SETOPTIONS call can be used to enable and disable the card
+	and to ask the driver to call panic if the system overheats.
+
+sbc60xxwdt.c -- 60xx Single Board Computer
+
+	Hardcoded timeout of 10 seconds
+
+	Does not support CONFIG_WATCHDOG_NOWAYOUT, but has the magic
+	character 'V' close handling.
+
+	No bits set in GETSUPPORT
+
+scx200.c -- National SCx200 CPUs
+
+	Not in the kernel yet.
+
+	The timeout is set using a module parameter "margin" which
+	defaults to 60 seconds.  The timeout can also be set using
+	SETTIMEOUT and read using GETTIMEOUT.
+
+	Supports a module parameter "nowayout" that is initialized
+	with the value of CONFIG_WATCHDOG_NOWAYOUT.  Also supports the
+	magic character 'V' handling.
+
+shwdt.c -- SuperH 3/4 processors
+
+	[FIXME -- I'm unable to tell what the timeout is]
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT
+
+	GETSUPPORT returns WDIOF_KEEPALIVEPING, and the GETSTATUS call
+	returns if the device is open or not.  [FIXME -- silliness
+	again?]
+
+softdog.c -- Software watchdog
+
+	The timeout is set with the module parameter "soft_margin"
+	which defaults to 60 seconds, the timeout is also settable
+	using the SETTIMEOUT ioctl.
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT
+
+	WDIOF_SETTIMEOUT bit set in GETSUPPORT
+
+w83877f_wdt.c -- W83877F Computer
+
+	Hardcoded timeout of 30 seconds
+
+	Does not support CONFIG_WATCHDOG_NOWAYOUT, but has the magic
+	character 'V' close handling.
+
+	No bits set in GETSUPPORT
+
+wdt.c -- ICS WDT500/501 ISA and
+wdt_pci.c -- ICS WDT500/501 PCI
+
+	Default timeout of 60 seconds.  The timeout is also settable
+        using the SETTIMEOUT ioctl.
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT
+
+	GETSUPPORT returns with bits set depending on the actual
+	card. The WDT501 supports a lot of external monitoring, the
+	WDT500 much less.
+
+wdt285.c -- Footbridge watchdog
+
+	The timeout is set with the module parameter "soft_margin"
+	which defaults to 60 seconds.  The timeout is also settable
+	using the SETTIMEOUT ioctl.
+
+	Does not support CONFIG_WATCHDOG_NOWAYOUT
+
+	WDIOF_SETTIMEOUT bit set in GETSUPPORT
+
+wdt977.c -- Netwinder W83977AF chip
+
+	Hardcoded timeout of 3 minutes
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT
+
+	Does not support any ioctls at all.
+
diff --git a/MAINTAINERS b/MAINTAINERS
index 5f37f6e..5388402 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1437,8 +1437,6 @@
 M:	anton@samba.org
 L:	sparclinux@vger.kernel.org
 L:	ultralinux@vger.kernel.org
-W:	http://ultra.linux.cz
-W:	http://www.geog.ubc.ca/s_linux.html
 S:	Maintained
 
 SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER
diff --git a/Makefile b/Makefile
index b3aef7bd..cc61c40 100644
--- a/Makefile
+++ b/Makefile
@@ -1,12 +1,12 @@
 VERSION = 2
 PATCHLEVEL = 5
-SUBLEVEL = 7
-EXTRAVERSION =
+SUBLEVEL = 8
+EXTRAVERSION =-pre1
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
-KERNELPATH=kernel-$(shell echo $(KERNELRELEASE) | sed -e "s/-//")
+KERNELPATH=kernel-$(shell echo $(KERNELRELEASE) | sed -e "s/-//g")
 
 CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
 	  else if [ -x /bin/bash ]; then echo /bin/bash; \
@@ -341,7 +341,7 @@
 	$(CC) $(CFLAGS) $(CFLAGS_KERNEL) $(PROFILING) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) -c -o $*.o $<
 
 init/do_mounts.o: init/do_mounts.c include/config/MARKER
-	$(CC) $(CFLAGS) $(CFLAGS_KERNEL) $(PROFILING) -c -o $*.o $<
+	$(CC) $(CFLAGS) $(CFLAGS_KERNEL) $(PROFILING) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) -c -o $*.o $<
 
 fs lib mm ipc kernel drivers net sound: dummy
 	$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" $(subst $@, _dir_$@, $@)
diff --git a/Rules.make b/Rules.make
index 2d3c5fa..83f31b8 100644
--- a/Rules.make
+++ b/Rules.make
@@ -50,10 +50,10 @@
 #
 
 %.s: %.c
-	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -S $< -o $@
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -S $< -o $@
 
 %.i: %.c
-	$(CPP) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) $< > $@
+	$(CPP) $(CFLAGS) $(EXTRA_CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) $< > $@
 
 %.o: %.c
 	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -c -o $@ $<
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
index 4cfcab8..c3e028e 100644
--- a/arch/alpha/kernel/alpha_ksyms.c
+++ b/arch/alpha/kernel/alpha_ksyms.c
@@ -103,7 +103,6 @@
 EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(strncat);
 EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strchr);
 EXPORT_SYMBOL(strrchr);
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index 58c0ee0..42c3bf3 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -472,6 +472,7 @@
 	struct percpu_struct *cpu;
 	char *type_name, *var_name, *p;
 	void *kernel_end = _end; /* end of kernel */
+	char *args = command_line;
 
 	hwrpb = (struct hwrpb_struct*) __va(INIT_HWRPB->phys_addr);
 	boot_cpuid = hard_smp_processor_id();
@@ -509,7 +510,8 @@
 	/* 
 	 * Process command-line arguments.
 	 */
-	for (p = strtok(command_line, " \t"); p ; p = strtok(NULL, " \t")) {
+	while ((p = strsep(&args, " \t")) != NULL) {
+		if (!*p) continue;
 		if (strncmp(p, "alpha_mv=", 9) == 0) {
 			vec = get_sysvec_byname(p+9);
 			continue;
@@ -528,7 +530,7 @@
 		}
 	}
 
-	/* Replace the command line, now that we've killed it with strtok.  */
+	/* Replace the command line, now that we've killed it with strsep.  */
 	strcpy(command_line, saved_command_line);
 
 	/* If we want SRM console printk echoing early, do it now. */
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index a84ba04..5724dbd4 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -180,7 +180,7 @@
 EXPORT_SYMBOL_NOVERS(strlen);
 EXPORT_SYMBOL_NOVERS(strnlen);
 EXPORT_SYMBOL_NOVERS(strpbrk);
-EXPORT_SYMBOL_NOVERS(strtok);
+EXPORT_SYMBOL_NOVERS(strsep);
 EXPORT_SYMBOL_NOVERS(strrchr);
 EXPORT_SYMBOL_NOVERS(strstr);
 EXPORT_SYMBOL_NOVERS(memset);
diff --git a/arch/arm/mach-arc/dma.c b/arch/arm/mach-arc/dma.c
index 26a4e24..9012117 100644
--- a/arch/arm/mach-arc/dma.c
+++ b/arch/arm/mach-arc/dma.c
@@ -100,7 +100,7 @@
 	/* 10/1/1999 DAG - Presume whether there is an outstanding command? */
 	extern unsigned int fdc1772_fdc_int_done;
 
-	* Explicit! If the int done is 0 then 1 int to go */
+	/* Explicit! If the int done is 0 then 1 int to go */
 	return (fdc1772_fdc_int_done==0)?1:0;
 }
 
diff --git a/arch/cris/drivers/ethernet.c b/arch/cris/drivers/ethernet.c
index 47fe0a6..a01c0ec 100644
--- a/arch/cris/drivers/ethernet.c
+++ b/arch/cris/drivers/ethernet.c
@@ -996,7 +996,7 @@
 	int i;
 #endif
 
-	if (!led_active && jiffies > led_next_time) {
+	if (!led_active && time_after(jiffies, led_next_time)) {
 		/* light the network leds depending on the current speed. */
 		e100_set_network_leds(NETWORK_ACTIVITY);
 
@@ -1288,7 +1288,7 @@
 {
 	D(printk("e100 send pack, buf 0x%x len %d\n", buf, length));
 
-	if (!led_active && jiffies > led_next_time) {
+	if (!led_active && time_after(jiffies, led_next_time)) {
 		/* light the network leds depending on the current speed. */
 		e100_set_network_leds(NETWORK_ACTIVITY);
 
@@ -1313,7 +1313,7 @@
 static void
 e100_clear_network_leds(unsigned long dummy)
 {
-	if (led_active && jiffies > led_next_time) {
+	if (led_active && jiffies > time_after(jiffies, led_next_time)) {
 		e100_set_network_leds(NO_NETWORK_ACTIVITY);
 
 		/* Set the earliest time we may set the LED */
diff --git a/arch/cris/drivers/gpio.c b/arch/cris/drivers/gpio.c
index c454e5d..445dfaa 100644
--- a/arch/cris/drivers/gpio.c
+++ b/arch/cris/drivers/gpio.c
@@ -217,7 +217,7 @@
 gpio_open(struct inode *inode, struct file *filp)
 {
 	struct gpio_private *priv;
-	int p = MINOR(inode->i_rdev);
+	int p = minor(inode->i_rdev);
 
 	if (p >= NUM_PORTS && p != LEDS)
 		return -EINVAL;
diff --git a/arch/cris/drivers/ide.c b/arch/cris/drivers/ide.c
index 95fe8ed..79a617d 100644
--- a/arch/cris/drivers/ide.c
+++ b/arch/cris/drivers/ide.c
@@ -271,10 +271,10 @@
 
 	printk("ide: ETRAX 100LX built-in ATA DMA controller\n");
 
-	/* first fill in some stuff in the ide_hwifs fields */
+	/* first initialize the channel interface data */
 	
 	for(h = 0; h < MAX_HWIFS; h++) {
-		ide_hwif_t *hwif = &ide_hwifs[h];
+		struct ata_channel *hwif = &ide_hwifs[h];
 		hwif->chipset = ide_etrax100;
 		hwif->tuneproc = &tune_e100_ide;
 		hwif->dmaproc = &e100_dmaproc;
@@ -355,7 +355,7 @@
 	printk("ide: waiting %d seconds for drives to regain consciousness\n", CONFIG_ETRAX_IDE_DELAY);
 
 	h = jiffies + (CONFIG_ETRAX_IDE_DELAY * HZ);
-	while(jiffies < h) ;
+	while(time_before(jiffies, h)) ;
 
   /* reset the dma channels we will use */
 
@@ -717,7 +717,7 @@
 	LED_DISK_READ(0);
 	LED_DISK_WRITE(0);
 
-	dma_stat = HWIF(drive)->dmaproc(ide_dma_end, drive);
+	dma_stat = drive->channel->dmaproc(ide_dma_end, drive);
 	stat = GET_STAT();			/* get drive status */
 	if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
 		if (!dma_stat) {
@@ -798,7 +798,7 @@
 	 * not a diskdrive.
 	 */
 
-        if (drive->media != ide_disk)
+        if (drive->type != ATA_DISK)
                 return 0;
 
  dma_begin:
@@ -809,7 +809,7 @@
 		WAIT_DMA(ATA_RX_DMA_NBR);
 
 		/* set up the Etrax DMA descriptors */
-		
+
 		if(e100_ide_build_dmatable (drive))
 			return 1;
 
@@ -902,7 +902,7 @@
  * --- Marcin Dalecki
  */
 
-void ide_release_dma (ide_hwif_t *hwif)
+void ide_release_dma(struct ata_channel *hwif)
 {
 	/* empty */
 }
diff --git a/arch/cris/kernel/ksyms.c b/arch/cris/kernel/ksyms.c
index ef79813..4d2cbc1 100644
--- a/arch/cris/kernel/ksyms.c
+++ b/arch/cris/kernel/ksyms.c
@@ -38,9 +38,7 @@
 /* String functions */
 EXPORT_SYMBOL(memcmp);
 EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strpbrk);
-EXPORT_SYMBOL(simple_strtol);
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strcpy);
 EXPORT_SYMBOL(strchr);
diff --git a/arch/i386/Config.help b/arch/i386/Config.help
index dbcd190..d4f8b78 100644
--- a/arch/i386/Config.help
+++ b/arch/i386/Config.help
@@ -128,6 +128,12 @@
 
   If unsure, say "off".
 
+CONFIG_HIGHPTE
+  The VM uses one page table entry for each page of physical memory.
+  For systems with a lot of RAM, this can be wasteful of precious
+  low memory.  Setting this option will put user-space page table
+  entries in high memory.
+
 CONFIG_HIGHMEM4G
   Select this if you have a 32-bit processor and between 1 and 4
   gigabytes of physical RAM.
@@ -797,6 +803,30 @@
   a work-around for a number of buggy BIOSes. Switch this option on if
   your computer crashes instead of powering off properly.
 
+CONFIG_X86_MCE
+  Machine Check Exception support allows the processor to notify the
+  kernel if it detects a problem (e.g. overheating, component failure).
+  The action the kernel takes depends on the severity of the problem,
+  ranging from a warning message on the console, to halting the machine.
+  Your processor must be a Pentium or newer to support this - check the
+  flags in /proc/cpuinfo for mce.  Note that some older Pentium systems
+  have a design flaw which leads to false MCE events - hence MCE is
+  disabled on all P5 processors, unless explicitly enabled with "mce"
+  as a boot argument.  Similarly, if MCE is built in and creates a
+  problem on some new non-standard machine, you can boot with "nomce"
+  to disable it.  MCE support simply ignores non-MCE processors like
+  the 386 and 486, so nearly everyone can say Y here.
+
+CONFIG_X86_MCE_NONFATAL
+  Enabling this feature starts a timer that triggers every 5 seconds which
+  will look at the machine check registers to see if anything happened.
+  Non-fatal problems automatically get corrected (but still logged).
+  Disable this if you don't want to see these messages.
+  Seeing the messages this option prints out may be indicative of dying hardware,
+  or out-of-spec (ie, overclocked) hardware.
+  This option only does something on hardware with Intel P6 style MCE.
+  (Pentium Pro and above, AMD Athlon/Duron)
+				 
 CONFIG_TOSHIBA
   This adds a driver to safely access the System Management Mode of
   the CPU on Toshiba portables with a genuine Toshiba BIOS. It does
@@ -903,3 +933,6 @@
   of the BUG call as well as the EIP and oops trace.  This aids
   debugging but costs about 70-100K of memory.
 
+CONFIG_DEBUG_OBSOLETE
+  Say Y here if you want to reduce the chances of the tree compiling,
+  and are prepared to dig into driver internals to fix compile errors.
diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
index 100c19b..d738905 100644
--- a/arch/i386/boot/setup.S
+++ b/arch/i386/boot/setup.S
@@ -544,7 +544,7 @@
 	cmpw	$0, %cs:realmode_swtch
 	jz	rmodeswtch_normal
 
-	lcall	*%cs:realmode_swtch
+	lcall	%cs:realmode_swtch
 
 	jmp	rmodeswtch_end
 
diff --git a/arch/i386/config.in b/arch/i386/config.in
index b310959..771fa43 100644
--- a/arch/i386/config.in
+++ b/arch/i386/config.in
@@ -25,6 +25,7 @@
 	 Pentium-4				CONFIG_MPENTIUM4 \
 	 K6/K6-II/K6-III			CONFIG_MK6 \
 	 Athlon/Duron/K7			CONFIG_MK7 \
+	 Elan					CONFIG_MELAN \
 	 Crusoe					CONFIG_MCRUSOE \
 	 Winchip-C6				CONFIG_MWINCHIPC6 \
 	 Winchip-2				CONFIG_MWINCHIP2 \
@@ -119,6 +120,11 @@
    define_bool CONFIG_X86_PGE y
    define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
 fi
+if [ "$CONFIG_MELAN" = "y" ]; then
+   define_int  CONFIG_X86_L1_CACHE_SHIFT 4
+   define_bool CONFIG_X86_USE_STRING_486 y
+   define_bool CONFIG_X86_ALIGNMENT_16 y
+fi
 if [ "$CONFIG_MCYRIXIII" = "y" ]; then
    define_int  CONFIG_X86_L1_CACHE_SHIFT 5
    define_bool CONFIG_X86_TSC y
@@ -150,6 +156,10 @@
    define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
    define_bool CONFIG_X86_OOSTORE y
 fi
+
+bool 'Machine Check Exception' CONFIG_X86_MCE
+dep_bool 'Check for non-fatal errors' CONFIG_X86_MCE_NONFATAL $CONFIG_X86_MCE
+
 tristate 'Toshiba Laptop support' CONFIG_TOSHIBA
 tristate 'Dell laptop support' CONFIG_I8K
 
@@ -160,25 +170,20 @@
 choice 'High Memory Support' \
 	"off           CONFIG_NOHIGHMEM \
 	 4GB           CONFIG_HIGHMEM4G \
-	 4GB-highpte   CONFIG_HIGHMEM4G_HIGHPTE \
-	 64GB          CONFIG_HIGHMEM64G \
-	 64GB-highpte  CONFIG_HIGHMEM64G_HIGHPTE" off
+	 64GB          CONFIG_HIGHMEM64G" off
+
+if [ "$CONFIG_HIGHMEM4G" = "y" -o "$CONFIG_HIGHMEM64G" = "y" ]; then
+   bool 'Use high memory pte support' CONFIG_HIGHPTE
+fi
+
 if [ "$CONFIG_HIGHMEM4G" = "y" ]; then
    define_bool CONFIG_HIGHMEM y
 fi
-if [ "$CONFIG_HIGHMEM4G_HIGHPTE" = "y" ]; then
-   define_bool CONFIG_HIGHMEM y
-   define_bool CONFIG_HIGHPTE y
-fi
+
 if [ "$CONFIG_HIGHMEM64G" = "y" ]; then
    define_bool CONFIG_HIGHMEM y
    define_bool CONFIG_X86_PAE y
 fi
-if [ "$CONFIG_HIGHMEM64G_HIGHPTE" = "y" ]; then
-   define_bool CONFIG_HIGHMEM y
-   define_bool CONFIG_HIGHPTE y
-   define_bool CONFIG_X86_PAE y
-fi
 
 bool 'Math emulation' CONFIG_MATH_EMULATION
 bool 'MTRR (Memory Type Range Register) support' CONFIG_MTRR
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 2c7f6ed..ce94a6f 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -39,6 +39,7 @@
 # CONFIG_MPENTIUM4 is not set
 # CONFIG_MK6 is not set
 # CONFIG_MK7 is not set
+# CONFIG_MELAN is not set
 # CONFIG_MCRUSOE is not set
 # CONFIG_MWINCHIPC6 is not set
 # CONFIG_MWINCHIP2 is not set
@@ -57,6 +58,8 @@
 CONFIG_X86_GOOD_APIC=y
 CONFIG_X86_PGE=y
 CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_MCE=y
+# CONFIG_X86_MCE_NONFATAL is not set
 # CONFIG_TOSHIBA is not set
 # CONFIG_I8K is not set
 # CONFIG_MICROCODE is not set
@@ -64,9 +67,7 @@
 # CONFIG_X86_CPUID is not set
 CONFIG_NOHIGHMEM=y
 # CONFIG_HIGHMEM4G is not set
-# CONFIG_HIGHMEM4G_HIGHPTE is not set
 # CONFIG_HIGHMEM64G is not set
-# CONFIG_HIGHMEM64G_HIGHPTE is not set
 # CONFIG_MATH_EMULATION is not set
 # CONFIG_MTRR is not set
 CONFIG_SMP=y
@@ -103,7 +104,6 @@
 # CONFIG_I82092 is not set
 # CONFIG_I82365 is not set
 # CONFIG_TCIC is not set
-# CONFIG_PCMCIA_SA1100 is not set
 
 #
 # PCI Hotplug Support
@@ -268,7 +268,6 @@
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_WDC_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD74XX is not set
-# CONFIG_AMD74XX_OVERRIDE is not set
 # CONFIG_BLK_DEV_CMD64X is not set
 # CONFIG_BLK_DEV_CY82C693 is not set
 # CONFIG_BLK_DEV_CS5530 is not set
@@ -276,7 +275,6 @@
 # CONFIG_HPT34X_AUTODMA is not set
 # CONFIG_BLK_DEV_HPT366 is not set
 CONFIG_BLK_DEV_PIIX=y
-CONFIG_PIIX_TUNING=y
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_OPTI621 is not set
 # CONFIG_BLK_DEV_PDC_ADMA is not set
@@ -291,7 +289,6 @@
 # CONFIG_IDEDMA_IVB is not set
 CONFIG_IDEDMA_AUTO=y
 # CONFIG_DMA_NONPCI is not set
-CONFIG_BLK_DEV_IDE_MODES=y
 # CONFIG_BLK_DEV_ATARAID is not set
 # CONFIG_BLK_DEV_ATARAID_PDC is not set
 # CONFIG_BLK_DEV_ATARAID_HPT is not set
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 47fda4a..f23c374 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -18,7 +18,8 @@
 
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
 		ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
-		pci-dma.o i386_ksyms.o i387.o bluesmoke.o dmi_scan.o
+		pci-dma.o i386_ksyms.o i387.o bluesmoke.o dmi_scan.o \
+		bootflag.o
 
 
 ifdef CONFIG_PCI
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 5072e08..cb80ad4 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -90,7 +90,7 @@
 		apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);
 	v = GET_APIC_VERSION(apic_read(APIC_LVR));
 	if (APIC_INTEGRATED(v)) {	/* !82489DX */
-		if (maxlvt > 3)
+		if (maxlvt > 3)		/* Due to Pentium errata 3AP and 11AP. */
 			apic_write(APIC_ESR, 0);
 		apic_read(APIC_ESR);
 	}
@@ -449,6 +449,7 @@
 	unsigned int apic_lvterr;
 	unsigned int apic_tmict;
 	unsigned int apic_tdcr;
+	unsigned int apic_thmr;
 } apic_pm_state;
 
 static void apic_pm_suspend(void *data)
@@ -470,6 +471,7 @@
 	apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR);
 	apic_pm_state.apic_tmict = apic_read(APIC_TMICT);
 	apic_pm_state.apic_tdcr = apic_read(APIC_TDCR);
+	apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
 	__save_flags(flags);
 	__cli();
 	disable_local_APIC();
@@ -498,6 +500,7 @@
 	apic_write(APIC_SPIV, apic_pm_state.apic_spiv);
 	apic_write(APIC_LVT0, apic_pm_state.apic_lvt0);
 	apic_write(APIC_LVT1, apic_pm_state.apic_lvt1);
+	apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr);
 	apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc);
 	apic_write(APIC_LVTT, apic_pm_state.apic_lvtt);
 	apic_write(APIC_TDCR, apic_pm_state.apic_tdcr);
diff --git a/arch/i386/kernel/bluesmoke.c b/arch/i386/kernel/bluesmoke.c
index 63db0ab..ac636f46 100644
--- a/arch/i386/kernel/bluesmoke.c
+++ b/arch/i386/kernel/bluesmoke.c
@@ -3,24 +3,138 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/config.h>
+#include <linux/irq.h>
 #include <asm/processor.h> 
+#include <asm/system.h>
 #include <asm/msr.h>
+#include <asm/apic.h>
+#include <asm/pgtable.h>
+
+#ifdef CONFIG_X86_MCE
 
 static int mce_disabled __initdata = 0;
 
+static int banks;
+
+/*
+ * If we get an MCE, we don't know what state the caches/TLB's are
+ * going to be in, so we throw them all away.
+ */
+static void inline flush_all (void)
+{   
+	__asm__ __volatile__ ("invd": : );
+	__flush_tlb();
+}
+
+/*
+ *	P4/Xeon Thermal transition interrupt handler
+ */
+
+static void intel_thermal_interrupt(struct pt_regs *regs)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+	u32 l, h;
+	unsigned int cpu = smp_processor_id();
+
+	ack_APIC_irq();
+
+	rdmsr(MSR_IA32_THERM_STATUS, l, h);
+	if (l & 1) {
+		printk(KERN_EMERG "CPU#%d: Temperature above threshold\n", cpu);
+		printk(KERN_EMERG "CPU#%d: Running in modulated clock mode\n", cpu);
+	} else {
+		printk(KERN_INFO "CPU#%d: Temperature/speed normal\n", cpu);
+	}
+#endif
+}
+
+static void unexpected_thermal_interrupt(struct pt_regs *regs)
+{	
+	printk(KERN_ERR "CPU#%d: Unexpected LVT TMR interrupt!\n", smp_processor_id());
+}
+
+/*
+ *	Thermal interrupt handler for this CPU setup
+ */
+
+static void (*vendor_thermal_interrupt)(struct pt_regs *regs) = unexpected_thermal_interrupt;
+
+asmlinkage void smp_thermal_interrupt(struct pt_regs regs)
+{
+	vendor_thermal_interrupt(&regs);
+}
+
+/* P4/Xeon Thermal regulation detect and init */
+
+static void __init intel_init_thermal(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+	u32 l, h;
+	unsigned int cpu = smp_processor_id();
+
+	/* Thermal monitoring */
+	if (!test_bit(X86_FEATURE_ACPI, &c->x86_capability))
+		return;	/* -ENODEV */
+	
+	/* Clock modulation */
+	if (!test_bit(X86_FEATURE_ACC, &c->x86_capability))
+		return;	/* -ENODEV */
+
+	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
+	/* first check if its enabled already, in which case there might
+	 * be some SMM goo which handles it, so we can't even put a handler
+	 * since it might be delivered via SMI already -zwanem.
+	 */
+
+	if (l & (1<<3)) {
+		printk(KERN_DEBUG "CPU#%d: Thermal monitoring already enabled\n", cpu);
+	} else {
+		wrmsr(MSR_IA32_MISC_ENABLE, l | (1<<3), h);
+		printk(KERN_INFO "CPU#%d: Thermal monitoring enabled\n", cpu);
+	}
+
+	/* check wether a vector already exists */	
+	l = apic_read(APIC_LVTTHMR);
+	if (l & 0xff) {
+		printk(KERN_DEBUG "CPU#%d: Thermal LVT already handled\n", cpu);
+		return; /* -EBUSY */
+	}
+	
+	wrmsr(MSR_IA32_MISC_ENABLE, l | (1<<3), h);
+	printk(KERN_INFO "CPU#%d: Thermal monitoring enabled\n", cpu);
+	
+	/* The temperature transition interrupt handler setup */
+	l = THERMAL_APIC_VECTOR;		/* our delivery vector */
+	l |= (APIC_DM_FIXED | APIC_LVT_MASKED);	/* we'll mask till we're ready */
+	apic_write_around(APIC_LVTTHMR, l);
+
+	rdmsr(MSR_IA32_THERM_INTERRUPT, l, h);
+	wrmsr(MSR_IA32_THERM_INTERRUPT, l | 0x3 , h);
+
+	/* ok we're good to go... */
+	vendor_thermal_interrupt = intel_thermal_interrupt;
+	l = apic_read(APIC_LVTTHMR);
+	apic_write_around(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
+
+	return;
+#endif
+}
+
 /*
  *	Machine Check Handler For PII/PIII
  */
 
-static int banks;
-
 static void intel_machine_check(struct pt_regs * regs, long error_code)
 {
 	int recover=1;
 	u32 alow, ahigh, high, low;
 	u32 mcgstl, mcgsth;
 	int i;
-	
+
+	flush_all();
+
 	rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
 	if(mcgstl&(1<<0))	/* Recoverable ? */
 		recover=0;
@@ -41,13 +155,12 @@
 			if(high&(1<<27))
 			{
 				rdmsr(MSR_IA32_MC0_MISC+i*4, alow, ahigh);
-				printk("[%08x%08x]", alow, ahigh);
+				printk("[%08x%08x]", ahigh, alow);
 			}
 			if(high&(1<<26))
 			{
 				rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh);
-				printk(" at %08x%08x", 
-					ahigh, alow);
+				printk(" at %08x%08x", ahigh, alow);
 			}
 			printk("\n");
 			/* Clear it */
@@ -109,8 +222,55 @@
 	machine_check_vector(regs, error_code);
 }
 
+
+#ifdef CONFIG_X86_MCE_NONFATAL
+struct timer_list mce_timer;
+
+static void mce_checkregs (unsigned int cpu)
+{
+	u32 low, high;
+	int i;
+
+	if (cpu!=smp_processor_id())
+		BUG();
+
+	for (i=0; i<banks; i++) {
+		rdmsr(MSR_IA32_MC0_STATUS+i*4, low, high);
+
+		if ((low | high) != 0) {
+			flush_all();
+			printk (KERN_EMERG "MCE: The hardware reports a non fatal, correctable incident occured on CPU %d.\n", smp_processor_id());
+			printk (KERN_EMERG "Bank %d: %08x%08x\n", i, high, low);
+
+			/* Scrub the error so we don't pick it up in 5 seconds time. */
+			wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
+
+			/* Serialize */
+			wmb();
+		}
+	}
+
+	/* Refresh the timer. */
+	mce_timer.expires = jiffies + 5 * HZ;
+	add_timer (&mce_timer);
+}
+
+static void mce_timerfunc (unsigned long data)
+{
+	int i;
+
+	for (i=0; i<smp_num_cpus; i++) {
+		if (i == smp_processor_id())
+			mce_checkregs(i);
+		else
+			smp_call_function (mce_checkregs, i, 1, 1);
+	}
+}
+#endif
+
+
 /*
- *	Set up machine check reporting for Intel processors
+ *	Set up machine check reporting for processors with Intel style MCE
  */
 
 static void __init intel_mcheck_init(struct cpuinfo_x86 *c)
@@ -164,19 +324,27 @@
 	if(done==0)
 		printk(KERN_INFO "Intel machine check architecture supported.\n");
 	rdmsr(MSR_IA32_MCG_CAP, l, h);
-	if(l&(1<<8))
+	if(l&(1<<8))	/* Control register present ? */
 		wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
 	banks = l&0xff;
-	for(i=1;i<banks;i++)
-	{
-		wrmsr(MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
+
+	/* Don't enable bank 0 on intel P6 cores, it goes bang quickly. */
+	if (c->x86_vendor == X86_VENDOR_INTEL && c->x86 == 6) {
+		for(i=1; i<banks; i++)
+			wrmsr(MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
+	} else {
+		for(i=0; i<banks; i++)
+			wrmsr(MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
 	}
-	for(i=0;i<banks;i++)
-	{
+
+	for(i=0; i<banks; i++)
 		wrmsr(MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
-	}
+
 	set_in_cr4(X86_CR4_MCE);
 	printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", smp_processor_id());
+	
+	intel_init_thermal(c);
+
 	done=1;
 }
 
@@ -206,28 +374,36 @@
  *	This has to be run for each processor
  */
 
-
-
 void __init mcheck_init(struct cpuinfo_x86 *c)
 {
 	if(mce_disabled==1)
 		return;
-		
+
 	switch(c->x86_vendor)
 	{
 		case X86_VENDOR_AMD:
-			/*
-			 *	AMD K7 machine check is Intel like
-			 */
-			if(c->x86 == 6)
+			/* AMD K7 machine check is Intel like */
+			if(c->x86 == 6) {
 				intel_mcheck_init(c);
+#ifdef CONFIG_X86_MCE_NONFATAL
+				/* Set the timer to check for non-fatal errors every 5 seconds */
+				init_timer (&mce_timer);
+				mce_timer.expires = jiffies + 5 * HZ;
+				mce_timer.data = 0;
+				mce_timer.function = &mce_timerfunc;
+				add_timer (&mce_timer);
+#endif
+			}
 			break;
+
 		case X86_VENDOR_INTEL:
 			intel_mcheck_init(c);
 			break;
+
 		case X86_VENDOR_CENTAUR:
 			winchip_mcheck_init(c);
 			break;
+
 		default:
 			break;
 	}
@@ -247,3 +423,9 @@
 
 __setup("nomce", mcheck_disable);
 __setup("mce", mcheck_enable);
+
+#else
+asmlinkage void do_machine_check(struct pt_regs * regs, long error_code) {}
+asmlinkage void smp_thermal_interrupt(struct pt_regs regs) {}
+void __init mcheck_init(struct cpuinfo_x86 *c) {}
+#endif
diff --git a/arch/i386/kernel/bootflag.c b/arch/i386/kernel/bootflag.c
new file mode 100644
index 0000000..ed98c857
--- /dev/null
+++ b/arch/i386/kernel/bootflag.c
@@ -0,0 +1,253 @@
+/*
+ *	Implement 'Simple Boot Flag Specification 1.0'
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+
+#include <linux/mc146818rtc.h>
+
+
+#define SBF_RESERVED (0x78)
+#define SBF_PNPOS    (1<<0)
+#define SBF_BOOTING  (1<<1)
+#define SBF_DIAG     (1<<2)
+#define SBF_PARITY   (1<<7)
+
+
+struct sbf_boot
+{
+	u8 sbf_signature[4];
+	u32 sbf_len;
+	u8 sbf_revision __attribute((packed));
+	u8 sbf_csum __attribute((packed));
+	u8 sbf_oemid[6] __attribute((packed));
+	u8 sbf_oemtable[8] __attribute((packed));
+	u8 sbf_revdata[4] __attribute((packed));
+	u8 sbf_creator[4] __attribute((packed));
+	u8 sbf_crearev[4] __attribute((packed));
+	u8 sbf_cmos __attribute((packed));
+	u8 sbf_spare[3] __attribute((packed));
+};
+
+
+static int sbf_port __initdata = -1;
+
+static int __init sbf_struct_valid(unsigned long tptr)
+{
+	u8 *ap;
+	u8 v;
+	unsigned int i;
+	struct sbf_boot sb;
+	
+	memcpy_fromio(&sb, tptr, sizeof(sb));
+
+	if(sb.sbf_len != 40 && sb.sbf_len != 39)
+		// 39 on IBM ThinkPad A21m, BIOS version 1.02b (KXET24WW; 2000-12-19).
+		return 0;
+
+	ap = (u8 *)&sb;
+	v= 0;
+	
+	for(i=0;i<sb.sbf_len;i++)
+		v+=*ap++;
+		
+	if(v)
+		return 0;
+
+	if(memcmp(sb.sbf_signature, "BOOT", 4))
+		return 0;
+
+	if (sb.sbf_len == 39)
+		printk (KERN_WARNING "SBF: ACPI BOOT descriptor is wrong length (%d)\n",
+			sb.sbf_len);
+
+	sbf_port = sb.sbf_cmos;	/* Save CMOS port */
+	return 1;
+}
+
+static int __init parity(u8 v)
+{
+	int x = 0;
+	int i;
+	
+	for(i=0;i<8;i++)
+	{
+		x^=(v&1);
+		v>>=1;
+	}
+	return x;
+}
+
+static void __init sbf_write(u8 v)
+{
+	unsigned long flags;
+	if(sbf_port != -1)
+	{
+		v &= ~SBF_PARITY;
+		if(!parity(v))
+			v|=SBF_PARITY;
+
+		printk(KERN_INFO "SBF: Setting boot flags 0x%x\n",v);
+
+		spin_lock_irqsave(&rtc_lock, flags);
+		CMOS_WRITE(v, sbf_port);
+		spin_unlock_irqrestore(&rtc_lock, flags);
+	}
+}
+
+static u8 __init sbf_read(void)
+{
+	u8 v;
+	unsigned long flags;
+	if(sbf_port == -1)
+		return 0;
+	spin_lock_irqsave(&rtc_lock, flags);
+	v = CMOS_READ(sbf_port);
+	spin_unlock_irqrestore(&rtc_lock, flags);
+	return v;
+}
+
+static int __init sbf_value_valid(u8 v)
+{
+	if(v&SBF_RESERVED)		/* Reserved bits */
+		return 0;
+	if(!parity(v))
+		return 0;
+	return 1;
+}
+
+
+static void __init sbf_bootup(void)
+{
+	u8 v;
+	if(sbf_port == -1)
+		return;
+	v = sbf_read();
+	if(!sbf_value_valid(v))
+		printk(KERN_WARNING "SBF: Simple boot flag value 0x%x read from CMOS RAM was invalid\n",v);
+	v &= ~SBF_RESERVED;
+	v &= ~SBF_BOOTING;
+	v &= ~SBF_DIAG;
+#if defined(CONFIG_ISAPNP)
+	v |= SBF_PNPOS;
+#endif
+	sbf_write(v);
+}
+
+static int __init sbf_init(void)
+{
+	unsigned int i;
+	void *rsdt;
+	u32 rsdtlen = 0;
+	u32 rsdtbase = 0;
+	u8 sum = 0;
+	int n;
+	
+	u8 *p;
+	
+	for(i=0xE0000; i <= 0xFFFE0; i+=16)
+	{
+		p = phys_to_virt(i);
+		
+		if(memcmp(p, "RSD PTR ", 8))
+			continue;
+		
+		sum = 0;
+		for(n=0; n<20; n++)
+			sum+=p[n];
+			
+		if(sum != 0)
+			continue;
+			
+		/* So it says RSD PTR and it checksums... */
+
+		/*
+		 *	Process the RDSP pointer
+		 */
+	 
+		rsdtbase = *(u32 *)(p+16);
+		
+		/*
+		 *	RSDT length is ACPI 2 only, for ACPI 1 we must map
+		 *	and remap.
+		 */
+		 
+		if(p[15]>1)
+			rsdtlen = *(u32 *)(p+20);
+		else
+			rsdtlen = 36;
+
+		if(rsdtlen < 36 || rsdtlen > 1024)
+			continue;
+		break;
+	}
+	if(i>0xFFFE0)
+		return 0;
+		
+		
+	rsdt = ioremap(rsdtbase, rsdtlen);
+	if(rsdt == 0)
+		return 0;
+		
+	i = readl(rsdt + 4);
+	
+	/*
+	 *	Remap if needed
+	 */
+	 
+	if(i > rsdtlen)
+	{
+		rsdtlen = i;
+		iounmap(rsdt);
+		rsdt = ioremap(rsdtbase, rsdtlen);
+		if(rsdt == 0)
+			return 0;
+	}
+	
+	for(n = 0; n < i; n++)
+		sum += readb(rsdt + n);
+		
+	if(sum)
+	{
+		iounmap(rsdt);
+		return 0;
+	}
+	
+	/* Ok the RSDT checksums too */
+	
+	for(n = 36; n+3 < i; n += 4)
+	{
+		unsigned long rp = readl(rsdt+n);
+		int len = 4096;
+
+		if(rp > 0xFFFFFFFFUL - len)
+			len = 0xFFFFFFFFUL - rp;
+			
+		/* Too close to the end!! */
+		if(len < 20)
+			continue;
+		rp = (unsigned long)ioremap(rp, 4096);
+		if(rp == 0)
+			continue;
+		if(sbf_struct_valid(rp))
+		{
+			/* Found the BOOT table and processed it */
+			printk(KERN_INFO "SBF: Simple Boot Flag extension found and enabled.\n");
+		}
+		iounmap((void *)rp);
+	}
+	iounmap(rsdt);
+	sbf_bootup();
+	return 0;
+}
+
+module_init(sbf_init);
diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c
index 499b2fd..0c2bd6d 100644
--- a/arch/i386/kernel/cpuid.c
+++ b/arch/i386/kernel/cpuid.c
@@ -35,6 +35,7 @@
 #include <linux/poll.h>
 #include <linux/smp.h>
 #include <linux/major.h>
+#include <linux/fs.h>
 #include <linux/smp_lock.h>
 #include <linux/fs.h>
 
diff --git a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
index 25bc3d7..21b1edb 100644
--- a/arch/i386/kernel/dmi_scan.c
+++ b/arch/i386/kernel/dmi_scan.c
@@ -295,6 +295,22 @@
 	return 0;
 }
 
+/*
+ * Work around broken HP Pavilion Notebooks which assign USB to
+ * IRQ 9 even though it is actually wired to IRQ 11
+ */
+static __init int fix_broken_hp_bios_irq9(struct dmi_blacklist *d)
+{
+#ifdef CONFIG_PCI
+	extern int broken_hp_bios_irq9;
+	if (broken_hp_bios_irq9 == 0)
+	{
+		broken_hp_bios_irq9 = 1;
+		printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident);
+	}
+#endif
+	return 0;
+}
 
 /*
  *  Check for clue free BIOS implementations who use
@@ -438,6 +454,25 @@
 }
 
 /*
+ * The Microstar 6163-2 (a.k.a Pro) mainboard will hang shortly after
+ * resumes, and also at what appears to be asynchronous APM events,
+ * if the local APIC is enabled.
+ */
+static int __init apm_kills_local_apic(struct dmi_blacklist *d)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+	extern int dont_enable_local_apic;
+	if (apm_info.bios.version && !dont_enable_local_apic) {
+		dont_enable_local_apic = 1;
+		printk(KERN_WARNING "%s with broken BIOS detected. "
+		       "Refusing to enable the local APIC.\n",
+		       d->ident);
+	}
+#endif
+	return 0;
+}
+
+/*
  * The Intel AL440LX mainboard will hang randomly if the local APIC
  * timer is running and the APM BIOS hasn't been disabled.
  */
@@ -483,10 +518,10 @@
 			} },
 #endif			
 	{ broken_ps2_resume, "Dell Latitude C600", {	/* Handle problems with APM on the C600 */
-		        MATCH(DMI_SYS_VENDOR, "Dell"),
+			MATCH(DMI_SYS_VENDOR, "Dell"),
 			MATCH(DMI_PRODUCT_NAME, "Latitude C600"),
 			NO_MATCH, NO_MATCH
-	                } },
+			} },
 	{ broken_apm_power, "Dell Inspiron 5000e", {	/* Handle problems with APM on Inspiron 5000e */
 			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
 			MATCH(DMI_BIOS_VERSION, "A04"),
@@ -512,6 +547,11 @@
 			MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
 			NO_MATCH, NO_MATCH
 			} },
+	{ set_bios_reboot, "Dell PowerEdge 2400", {  /* Handle problems with rebooting on Dell 300/800's */
+			MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+			MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
+			NO_MATCH, NO_MATCH
+			} },
 	{ set_apm_ints, "Dell Inspiron", {	/* Allow interrupts during suspend on Dell Inspiron laptops*/
 			MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
 			MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"),
@@ -533,12 +573,23 @@
 			MATCH(DMI_PRODUCT_NAME, "Delhi3"),
 			NO_MATCH, NO_MATCH,
 			} },
+	{ apm_is_horked, "Fujitsu-Siemens", { /* APM crashes */
+			MATCH(DMI_BIOS_VENDOR, "hoenix/FUJITSU SIEMENS"),
+			MATCH(DMI_BIOS_VERSION, "Version1.01"),
+			NO_MATCH, NO_MATCH,
+			} },
 	{ apm_is_horked, "Sharp PC-PJ/AX", { /* APM crashes */
 			MATCH(DMI_SYS_VENDOR, "SHARP"),
 			MATCH(DMI_PRODUCT_NAME, "PC-PJ/AX"),
 			MATCH(DMI_BIOS_VENDOR,"SystemSoft"),
 			MATCH(DMI_BIOS_VERSION,"Version R2.08")
 			} },
+	{ apm_is_horked, "Dell Inspiron 2500", { /* APM crashes */
+			MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+			MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"),
+			MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
+			MATCH(DMI_BIOS_VERSION,"A11")
+			} },
 	{ sony_vaio_laptop, "Sony Vaio", { /* This is a Sony Vaio laptop */
 			MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
 			MATCH(DMI_PRODUCT_NAME, "PCG-"),
@@ -548,7 +599,7 @@
 			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
 			MATCH(DMI_BIOS_VERSION, "R0206H"),
 			MATCH(DMI_BIOS_DATE, "08/23/99"), NO_MATCH
-	} },
+			} },
 
 	{ swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-N505VX */
 			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
@@ -574,6 +625,12 @@
 			MATCH(DMI_BIOS_DATE, "08/11/00"), NO_MATCH
 			} },
 
+	{ swab_apm_power_in_minutes, "Sony VAIO", {	/* Handle problems with APM on Sony Vaio PCG-Z600LEK(DE) */
+			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+			MATCH(DMI_BIOS_VERSION, "R0206Z3"),
+			MATCH(DMI_BIOS_DATE, "12/25/00"), NO_MATCH
+			} },
+
 	{ swab_apm_power_in_minutes, "Sony VAIO", {	/* Handle problems with APM on Sony Vaio PCG-Z505LS */
 			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
 			MATCH(DMI_BIOS_VERSION, "R0203D0"),
@@ -617,6 +674,17 @@
 			NO_MATCH, NO_MATCH
 			} },
 
+	{ local_apic_kills_bios, "IBM Thinkpad T20", {
+			MATCH(DMI_BOARD_VENDOR, "IBM"),
+			MATCH(DMI_BOARD_NAME, "264741U"),
+			NO_MATCH, NO_MATCH
+			} },
+
+	{ apm_kills_local_apic, "Microstar 6163", {
+			MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
+			MATCH(DMI_BOARD_NAME, "MS-6163"),
+			NO_MATCH, NO_MATCH } },
+
 	{ apm_kills_local_apic_timer, "Intel AL440LX", {
 			MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
 			MATCH(DMI_BOARD_NAME, "AL440LX"),
@@ -678,7 +746,14 @@
 			NO_MATCH, NO_MATCH
 			} },
 	 
-			
+	{ fix_broken_hp_bios_irq9, "HP Pavilion N5400 Series Laptop", {
+			MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			MATCH(DMI_BIOS_VERSION, "GE.M1.03"),
+			MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"),
+			MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736")
+			} },
+ 
+
 	/*
 	 *	Generic per vendor APM settings
 	 */
diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
index 5e21e7a..b7e346d 100644
--- a/arch/i386/kernel/i386_ksyms.c
+++ b/arch/i386/kernel/i386_ksyms.c
@@ -93,7 +93,6 @@
 EXPORT_SYMBOL_NOVERS(__get_user_2);
 EXPORT_SYMBOL_NOVERS(__get_user_4);
 
-EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strstr);
 
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index 64fb22f..40da258 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -51,6 +51,12 @@
  *		Bugfix for HT (Hyper-Threading) enabled processors
  *		whereby processor resources are shared by all logical processors
  *		in a single CPU package.
+ *	1.10	28 Feb 2002 Asit K Mallick <asit.k.mallick@intel.com> and
+ *		Tigran Aivazian <tigran@veritas.com>,
+ *		Serialize updates as required on HT processors due to speculative
+ *		nature of implementation.
+ *	1.11	22 Mar 2001 Tigran Aivazian <tigran@veritas.com>
+ *		Fix the panic when writing zero-length microcode chunk.
  */
 
 #include <linux/init.h>
@@ -60,12 +66,16 @@
 #include <linux/vmalloc.h>
 #include <linux/miscdevice.h>
 #include <linux/devfs_fs_kernel.h>
+#include <linux/spinlock.h>
 
 #include <asm/msr.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>
 
-#define MICROCODE_VERSION 	"1.09"
+
+static spinlock_t microcode_update_lock = SPIN_LOCK_UNLOCKED;
+
+#define MICROCODE_VERSION 	"1.11"
 
 MODULE_DESCRIPTION("Intel CPU (IA-32) microcode update driver");
 MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
@@ -195,7 +205,8 @@
 	struct cpuinfo_x86 *c = cpu_data + cpu_num;
 	struct update_req *req = update_req + cpu_num;
 	unsigned int pf = 0, val[2], rev, sig;
-	int i,found=0;
+	unsigned long flags;
+	int i;
 
 	req->err = 1; /* assume update will fail on this cpu */
 
@@ -216,8 +227,9 @@
 	for (i=0; i<microcode_num; i++)
 		if (microcode[i].sig == sig && microcode[i].pf == pf &&
 		    microcode[i].ldrver == 1 && microcode[i].hdrver == 1) {
-
-			found=1;
+			int sum = 0;
+			struct microcode *m = &microcode[i];
+			unsigned int *sump = (unsigned int *)(m+1);
 
 			printf("Microcode\n");
 			printf("   Header Revision %d\n",microcode[i].hdrver);
@@ -234,54 +246,69 @@
 			printf("   Loader Revision %x\n",microcode[i].ldrver);
 			printf("   Processor Flags %x\n\n",microcode[i].pf);
 
+			req->slot = i;
+
+			/* serialize access to update decision */
+			spin_lock_irqsave(&microcode_update_lock, flags);          
+
 			/* trick, to work even if there was no prior update by the BIOS */
 			wrmsr(MSR_IA32_UCODE_REV, 0, 0);
 			__asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
 
 			/* get current (on-cpu) revision into rev (ignore val[0]) */
 			rdmsr(MSR_IA32_UCODE_REV, val[0], rev);
+			
 			if (microcode[i].rev < rev) {
+				spin_unlock_irqrestore(&microcode_update_lock, flags);
 				printk(KERN_ERR 
-					"microcode: CPU%d not 'upgrading' to earlier revision"
-					" %d (current=%d)\n", cpu_num, microcode[i].rev, rev);
-			} else {
-				int sum = 0;
-				struct microcode *m = &microcode[i];
-				unsigned int *sump = (unsigned int *)(m+1);
-
-				while (--sump >= (unsigned int *)m)
-					sum += *sump;
-				if (sum != 0) {
-					printk(KERN_ERR "microcode: CPU%d aborting, "
-							"bad checksum\n", cpu_num);
-					break;
-				}
-
-				/* write microcode via MSR 0x79 */
-				wrmsr(MSR_IA32_UCODE_WRITE, (unsigned int)(m->bits), 0);
-
-				/* serialize */
-				__asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
-
-				/* get the current revision from MSR 0x8B */
-				rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
-
+				       "microcode: CPU%d not 'upgrading' to earlier revision"
+				       " %d (current=%d)\n", cpu_num, microcode[i].rev, rev);
+				return;
+			} else if (microcode[i].rev == rev) {
 				/* notify the caller of success on this cpu */
 				req->err = 0;
-				req->slot = i;
-
-				printk(KERN_INFO "microcode: CPU%d updated from revision "
-						"%d to %d, date=%08x\n", 
-						cpu_num, rev, val[1], m->date);
+				spin_unlock_irqrestore(&microcode_update_lock, flags);
+				printk(KERN_ERR 
+					"microcode: CPU%d already at revision"
+					" %d (current=%d)\n", cpu_num, microcode[i].rev, rev);
+				return;
 			}
-			break;
-		}
 
-	if(!found)
-		printk(KERN_ERR "microcode: CPU%d no microcode found! (sig=%x, pflags=%d)\n",
-				cpu_num, sig, pf);
+			/* Verify the checksum */
+			while (--sump >= (unsigned int *)m)
+				sum += *sump;
+			if (sum != 0) {
+				req->err = 1;
+				spin_unlock_irqrestore(&microcode_update_lock, flags);
+				printk(KERN_ERR "microcode: CPU%d aborting, "
+				       "bad checksum\n", cpu_num);
+				return;
+			}
+			
+			/* write microcode via MSR 0x79 */
+			wrmsr(MSR_IA32_UCODE_WRITE, (unsigned int)(m->bits), 0);
+
+			/* serialize */
+			__asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
+
+			/* get the current revision from MSR 0x8B */
+			rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
+
+			/* notify the caller of success on this cpu */
+			req->err = 0;
+			spin_unlock_irqrestore(&microcode_update_lock, flags);
+			printk(KERN_INFO "microcode: CPU%d updated from revision "
+			       "%d to %d, date=%08x\n", 
+			       cpu_num, rev, val[1], microcode[i].date);
+			return;
+		}
+	
+	printk(KERN_ERR
+	       "microcode: CPU%d no microcode found! (sig=%x, pflags=%d)\n", 
+	       cpu_num, sig, pf);
 }
 
+
 static ssize_t microcode_read(struct file *file, char *buf, size_t len, loff_t *ppos)
 {
 	ssize_t ret = 0;
@@ -305,11 +332,15 @@
 {
 	ssize_t ret;
 
-	if (len % sizeof(struct microcode) != 0) {
+	if (!len || len % sizeof(struct microcode) != 0) {
 		printk(KERN_ERR "microcode: can only write in N*%d bytes units\n", 
 			sizeof(struct microcode));
 		return -EINVAL;
 	}
+	if ((len >> PAGE_SHIFT) > num_physpages) {
+		printk(KERN_ERR "microcode: too much data (max %d pages)\n", num_physpages);
+		return -EINVAL;
+	}
 	down_write(&microcode_rwsem);
 	if (!mc_applied) {
 		mc_applied = kmalloc(smp_num_cpus*sizeof(struct microcode),
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index 313f05f..2df0c94 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -232,6 +232,7 @@
 	if (m->mpc_apicid > MAX_APICS) {
 		printk("Processor #%d INVALID. (Max ID: %d).\n",
 			m->mpc_apicid, MAX_APICS);
+		--num_processors;
 		return;
 	}
 	ver = m->mpc_apicver;
@@ -816,11 +817,13 @@
 	 * trustworthy, simply because the SMP table may have been
 	 * stomped on during early boot. These loaders are buggy and
 	 * should be fixed.
+	 *
+	 * MP1.4 SPEC states to only scan first 1K of 4K EBDA.
 	 */
 
 	address = *(unsigned short *)phys_to_virt(0x40E);
 	address <<= 4;
-	smp_scan_config(address, 0x1000);
+	smp_scan_config(address, 0x400);
 	if (smp_found_config)
 		printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.kernel.org if you experience SMP problems!\n");
 }
diff --git a/arch/i386/kernel/mtrr.c b/arch/i386/kernel/mtrr.c
index d93e7a7..2adc9dd 100644
--- a/arch/i386/kernel/mtrr.c
+++ b/arch/i386/kernel/mtrr.c
@@ -498,7 +498,6 @@
     case MTRR_IF_INTEL:
 	rdmsr (MTRRcap_MSR, config, dummy);
 	return (config & (1<<10));
-	return 1;
     case MTRR_IF_AMD_K6:
     case MTRR_IF_CENTAUR_MCR:
     case MTRR_IF_CYRIX_ARR:
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index f91e5a3..c0b10d8 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -8,6 +8,7 @@
  *  Fixes:
  *  Mikael Pettersson	: AMD K7 support for local APIC NMI watchdog.
  *  Mikael Pettersson	: Power Management for local APIC NMI watchdog.
+ *  Mikael Pettersson	: Pentium 4 support for local APIC NMI watchdog.
  */
 
 #include <linux/config.h>
@@ -43,6 +44,32 @@
 #define P6_EVENT_CPU_CLOCKS_NOT_HALTED	0x79
 #define P6_NMI_EVENT		P6_EVENT_CPU_CLOCKS_NOT_HALTED
 
+#define MSR_P4_MISC_ENABLE	0x1A0
+#define MSR_P4_MISC_ENABLE_PERF_AVAIL	(1<<7)
+#define MSR_P4_MISC_ENABLE_PEBS_UNAVAIL	(1<<12)
+#define MSR_P4_PERFCTR0		0x300
+#define MSR_P4_CCCR0		0x360
+#define P4_ESCR_EVENT_SELECT(N)	((N)<<25)
+#define P4_ESCR_OS		(1<<3)
+#define P4_ESCR_USR		(1<<2)
+#define P4_CCCR_OVF_PMI		(1<<26)
+#define P4_CCCR_THRESHOLD(N)	((N)<<20)
+#define P4_CCCR_COMPLEMENT	(1<<19)
+#define P4_CCCR_COMPARE		(1<<18)
+#define P4_CCCR_REQUIRED	(3<<16)
+#define P4_CCCR_ESCR_SELECT(N)	((N)<<13)
+#define P4_CCCR_ENABLE		(1<<12)
+/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
+   CRU_ESCR0 (with any non-null event selector) through a complemented
+   max threshold. [IA32-Vol3, Section 14.9.9] */
+#define MSR_P4_IQ_COUNTER0	0x30C
+#define MSR_P4_IQ_CCCR0		0x36C
+#define MSR_P4_CRU_ESCR0	0x3B8
+#define P4_NMI_CRU_ESCR0	(P4_ESCR_EVENT_SELECT(0x3F)|P4_ESCR_OS|P4_ESCR_USR)
+#define P4_NMI_IQ_CCCR0	\
+	(P4_CCCR_OVF_PMI|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT|	\
+	 P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
+
 int __init check_nmi_watchdog (void)
 {
 	irq_cpustat_t tmp[NR_CPUS];
@@ -84,11 +111,11 @@
 	/*
 	 * If any other x86 CPU has a local APIC, then
 	 * please test the NMI stuff there and send me the
-	 * missing bits. Right now Intel P6 and AMD K7 only.
+	 * missing bits. Right now Intel P6/P4 and AMD K7 only.
 	 */
 	if ((nmi == NMI_LOCAL_APIC) &&
 			(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
-			(boot_cpu_data.x86 == 6))
+			(boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15))
 		nmi_watchdog = nmi;
 	if ((nmi == NMI_LOCAL_APIC) &&
 			(boot_cpu_data.x86_vendor == X86_VENDOR_AMD) &&
@@ -118,7 +145,15 @@
 		wrmsr(MSR_K7_EVNTSEL0, 0, 0);
 		break;
 	case X86_VENDOR_INTEL:
-		wrmsr(MSR_IA32_EVNTSEL0, 0, 0);
+		switch (boot_cpu_data.x86) {
+		case 6:
+			wrmsr(MSR_P6_EVNTSEL0, 0, 0);
+			break;
+		case 15:
+			wrmsr(MSR_P4_IQ_CCCR0, 0, 0);
+			wrmsr(MSR_P4_CRU_ESCR0, 0, 0);
+			break;
+		}
 		break;
 	}
 }
@@ -157,17 +192,22 @@
  * Original code written by Keith Owens.
  */
 
+static void __pminit clear_msr_range(unsigned int base, unsigned int n)
+{
+	unsigned int i;
+
+	for(i = 0; i < n; ++i)
+		wrmsr(base+i, 0, 0);
+}
+
 static void __pminit setup_k7_watchdog(void)
 {
-	int i;
 	unsigned int evntsel;
 
 	nmi_perfctr_msr = MSR_K7_PERFCTR0;
 
-	for(i = 0; i < 4; ++i) {
-		wrmsr(MSR_K7_EVNTSEL0+i, 0, 0);
-		wrmsr(MSR_K7_PERFCTR0+i, 0, 0);
-	}
+	clear_msr_range(MSR_K7_EVNTSEL0, 4);
+	clear_msr_range(MSR_K7_PERFCTR0, 4);
 
 	evntsel = K7_EVNTSEL_INT
 		| K7_EVNTSEL_OS
@@ -184,27 +224,54 @@
 
 static void __pminit setup_p6_watchdog(void)
 {
-	int i;
 	unsigned int evntsel;
 
-	nmi_perfctr_msr = MSR_IA32_PERFCTR0;
+	nmi_perfctr_msr = MSR_P6_PERFCTR0;
 
-	for(i = 0; i < 2; ++i) {
-		wrmsr(MSR_IA32_EVNTSEL0+i, 0, 0);
-		wrmsr(MSR_IA32_PERFCTR0+i, 0, 0);
-	}
+	clear_msr_range(MSR_P6_EVNTSEL0, 2);
+	clear_msr_range(MSR_P6_PERFCTR0, 2);
 
 	evntsel = P6_EVNTSEL_INT
 		| P6_EVNTSEL_OS
 		| P6_EVNTSEL_USR
 		| P6_NMI_EVENT;
 
-	wrmsr(MSR_IA32_EVNTSEL0, evntsel, 0);
-	Dprintk("setting IA32_PERFCTR0 to %08lx\n", -(cpu_khz/nmi_hz*1000));
-	wrmsr(MSR_IA32_PERFCTR0, -(cpu_khz/nmi_hz*1000), 0);
+	wrmsr(MSR_P6_EVNTSEL0, evntsel, 0);
+	Dprintk("setting P6_PERFCTR0 to %08lx\n", -(cpu_khz/nmi_hz*1000));
+	wrmsr(MSR_P6_PERFCTR0, -(cpu_khz/nmi_hz*1000), 0);
 	apic_write(APIC_LVTPC, APIC_DM_NMI);
 	evntsel |= P6_EVNTSEL0_ENABLE;
-	wrmsr(MSR_IA32_EVNTSEL0, evntsel, 0);
+	wrmsr(MSR_P6_EVNTSEL0, evntsel, 0);
+}
+
+static int __pminit setup_p4_watchdog(void)
+{
+	unsigned int misc_enable, dummy;
+
+	rdmsr(MSR_P4_MISC_ENABLE, misc_enable, dummy);
+	if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL))
+		return 0;
+
+	nmi_perfctr_msr = MSR_P4_IQ_COUNTER0;
+
+	if (!(misc_enable & MSR_P4_MISC_ENABLE_PEBS_UNAVAIL))
+		clear_msr_range(0x3F1, 2);
+	/* MSR 0x3F0 seems to have a default value of 0xFC00, but current
+	   docs doesn't fully define it, so leave it alone for now. */
+	clear_msr_range(0x3A0, 31);
+	clear_msr_range(0x3C0, 6);
+	clear_msr_range(0x3C8, 6);
+	clear_msr_range(0x3E0, 2);
+	clear_msr_range(MSR_P4_CCCR0, 18);
+	clear_msr_range(MSR_P4_PERFCTR0, 18);
+
+	wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);
+	wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);
+	Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000));
+	wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1);
+	apic_write(APIC_LVTPC, APIC_DM_NMI);
+	wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0, 0);
+	return 1;
 }
 
 void __pminit setup_apic_nmi_watchdog (void)
@@ -216,9 +283,17 @@
 		setup_k7_watchdog();
 		break;
 	case X86_VENDOR_INTEL:
-		if (boot_cpu_data.x86 != 6)
+		switch (boot_cpu_data.x86) {
+		case 6:
+			setup_p6_watchdog();
+			break;
+		case 15:
+			if (!setup_p4_watchdog())
+				return;
+			break;
+		default:
 			return;
-		setup_p6_watchdog();
+		}
 		break;
 	default:
 		return;
@@ -296,6 +371,18 @@
 		last_irq_sums[cpu] = sum;
 		alert_counter[cpu] = 0;
 	}
-	if (nmi_perfctr_msr)
+	if (nmi_perfctr_msr) {
+		if (nmi_perfctr_msr == MSR_P4_IQ_COUNTER0) {
+			/*
+			 * P4 quirks:
+			 * - An overflown perfctr will assert its interrupt
+			 *   until the OVF flag in its CCCR is cleared.
+			 * - LVTPC is masked on interrupt and must be
+			 *   unmasked by the LVTPC handler.
+			 */
+			wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0, 0);
+			apic_write(APIC_LVTPC, APIC_DM_NMI);
+		}
 		wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1);
+	}
 }
diff --git a/arch/i386/kernel/pci-dma.c b/arch/i386/kernel/pci-dma.c
index 18a08cc..2031b85 100644
--- a/arch/i386/kernel/pci-dma.c
+++ b/arch/i386/kernel/pci-dma.c
@@ -19,7 +19,7 @@
 	void *ret;
 	int gfp = GFP_ATOMIC;
 
-	if (hwdev == NULL || hwdev->dma_mask != 0xffffffff)
+	if (hwdev == NULL || ((u32)hwdev->dma_mask != 0xffffffff))
 		gfp |= GFP_DMA;
 	ret = (void *)__get_free_pages(gfp, get_order(size));
 
diff --git a/arch/i386/kernel/pci-irq.c b/arch/i386/kernel/pci-irq.c
index 1595743..b489826 100644
--- a/arch/i386/kernel/pci-irq.c
+++ b/arch/i386/kernel/pci-irq.c
@@ -23,6 +23,7 @@
 #define PIRQ_VERSION 0x0100
 
 int pci_use_acpi_routing = 0;
+int broken_hp_bios_irq9;
 
 static struct irq_routing_table *pirq_table;
 
@@ -208,6 +209,24 @@
 }
 
 /*
+ * ITE 8330G pirq rules are nibble-based
+ * FIXME: pirqmap may be { 1, 0, 3, 2 },
+ * 	  2+3 are both mapped to irq 9 on my system
+ */
+static int pirq_ite_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+	static unsigned char pirqmap[4] = { 1, 0, 2, 3 };
+	return read_config_nybble(router,0x43, pirqmap[pirq-1]);
+}
+
+static int pirq_ite_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+	static unsigned char pirqmap[4] = { 1, 0, 2, 3 };
+	write_config_nybble(router, 0x43, pirqmap[pirq-1], irq);
+	return 1;
+}
+
+/*
  * OPTI: high four bits are nibble pointer..
  * I wonder what the low bits do?
  */
@@ -227,12 +246,12 @@
  */
 static int pirq_cyrix_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
 {
-	return read_config_nybble(router, 0x5C, pirq-1);
+	return read_config_nybble(router, 0x5C, (pirq-1)^1);
 }
 
 static int pirq_cyrix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
 {
-	write_config_nybble(router, 0x5C, pirq-1, irq);
+	write_config_nybble(router, 0x5C, (pirq-1)^1, irq);
 	return 1;
 }
 
@@ -445,10 +464,17 @@
 	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, pirq_piix_get, pirq_piix_set },
 	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX,   pirq_piix_get, pirq_piix_set },
 	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_0, pirq_piix_get, pirq_piix_set },
+	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, pirq_piix_get, pirq_piix_set },
+	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, pirq_piix_get, pirq_piix_set },
 	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, pirq_piix_get, pirq_piix_set },
+	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, pirq_piix_get, pirq_piix_set },
+	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, pirq_piix_get, pirq_piix_set },
+	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, pirq_piix_get, pirq_piix_set },
 
 	{ "ALI", PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, pirq_ali_get, pirq_ali_set },
 
+	{ "ITE", PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8330G_0, pirq_ite_get, pirq_ite_set },
+
 	{ "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, pirq_via_get, pirq_via_set },
 	{ "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, pirq_via_get, pirq_via_set },
 	{ "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, pirq_via_get, pirq_via_set },
@@ -589,6 +615,15 @@
 	DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, pirq_table->exclusive_irqs);
 	mask &= pcibios_irq_mask;
 
+	/* Work around broken HP Pavilion Notebooks which assign USB to
+	   IRQ 9 even though it is actually wired to IRQ 11 */
+
+	if (broken_hp_bios_irq9 && pirq == 0x59 && dev->irq == 9) {
+		dev->irq = 11;
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
+		r->set(pirq_router_dev, dev, pirq, 11);
+	}
+
 	/*
 	 * Find the best IRQ to assign: use the one
 	 * reported by the device if possible.
diff --git a/arch/i386/kernel/pci-pc.c b/arch/i386/kernel/pci-pc.c
index 7702a6d..9f40d43 100644
--- a/arch/i386/kernel/pci-pc.c
+++ b/arch/i386/kernel/pci-pc.c
@@ -1205,7 +1205,8 @@
 
         pci_read_config_byte(d, where, &v);
 	if (v & 0xe0) {
-		printk("Disabling broken memory write queue.\n");
+		printk("Disabling broken memory write queue: [%02x] %02x->%02x\n",
+			where, v, v & 0x1f);
 		v &= 0x1f; /* clear bits 5, 6, 7 */
 		pci_write_config_byte(d, where, v);
 	}
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index d3f11c8..bbeb875 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -99,6 +99,8 @@
 #endif
 #include <linux/highmem.h>
 #include <linux/bootmem.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
 #include <linux/seq_file.h>
 #include <linux/console.h>
 #include <asm/processor.h>
@@ -127,9 +129,6 @@
 /*
  * Bus types ..
  */
-#ifdef CONFIG_EISA
-int EISA_bus;
-#endif
 int MCA_bus;
 
 /* for MCA, but anyone else can use it if they want */
@@ -210,6 +209,10 @@
 	{ "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
 	{ "fpu", 0xf0, 0xff, IORESOURCE_BUSY }
 };
+#ifdef CONFIG_MELAN
+standard_io_resources[1] = { "pic1", 0x20, 0x21, IORESOURCE_BUSY };
+standard_io_resources[5] = { "pic2", 0xa0, 0xa1, IORESOURCE_BUSY };
+#endif
 
 #define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))
 
@@ -1240,7 +1243,7 @@
 }
 
 /*
- * Read Cyrix DEVID registers (DIR) to get more detailed info. about the CPU
+ * Read NSC/Cyrix DEVID registers (DIR) to get more detailed info. about the CPU
  */
 static void __init do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
 {
@@ -1315,7 +1318,7 @@
 static void __init check_cx686_slop(struct cpuinfo_x86 *c)
 {
 	unsigned long flags;
-	
+
 	if (Cx86_dir0_msb == 3) {
 		unsigned char ccr3, ccr5;
 
@@ -1325,7 +1328,7 @@
 		ccr5 = getCx86(CX86_CCR5);
 		if (ccr5 & 2)
 			setCx86(CX86_CCR5, ccr5 & 0xfd);  /* reset SLOP */
-		setCx86(CX86_CCR3, ccr3);                 /* disable MAPEN */
+		setCx86(CX86_CCR3, ccr3);		  /* disable MAPEN */
 		local_irq_restore(flags);
 
 		if (ccr5 & 2) { /* possible wrong calibration done */
@@ -1336,6 +1339,7 @@
 	}
 }
 
+
 static void __init init_cyrix(struct cpuinfo_x86 *c)
 {
 	unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0;
@@ -1402,17 +1406,12 @@
 		break;
 
 	case 4: /* MediaGX/GXm */
-		/*
-		 *	Life sometimes gets weiiiiiiiird if we use this
-		 *	on the MediaGX. So we turn it off for now. 
-		 */
-		
 #ifdef CONFIG_PCI
-		/* It isnt really a PCI quirk directly, but the cure is the
+		/* It isn't really a PCI quirk directly, but the cure is the
 		   same. The MediaGX has deep magic SMM stuff that handles the
 		   SB emulation. It thows away the fifo on disable_dma() which
 		   is wrong and ruins the audio. 
-                   
+
 		   Bug2: VSA1 has a wrap bug so that using maximum sized DMA 
 		   causes bad things. According to NatSemi VSA2 has another
 		   bug to do with 'hlt'. I've not seen any boards using VSA2
@@ -1427,15 +1426,26 @@
 
 		/* GXm supports extended cpuid levels 'ala' AMD */
 		if (c->cpuid_level == 2) {
+			/* Enable Natsemi MMX extensions */
+			setCx86(CX86_CCR7, getCx86(CX86_CCR7) | 1);
+
 			get_model_name(c);  /* get CPU marketing name */
-			clear_bit(X86_FEATURE_TSC, c->x86_capability);
+			/*
+			 *  The 5510/5520 companion chips have a funky PIT
+			 *  that breaks the TSC synchronizing, so turn it off
+			 */
+			if(pci_find_device(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510, NULL) ||
+				pci_find_device(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, NULL))
+				clear_bit(X86_FEATURE_TSC, c->x86_capability);
 			return;
 		}
 		else {  /* MediaGX */
 			Cx86_cb[2] = (dir0_lsn & 1) ? '3' : '4';
 			p = Cx86_cb+2;
 			c->x86_model = (dir1 & 0x20) ? 1 : 2;
+#ifndef CONFIG_CS5520
 			clear_bit(X86_FEATURE_TSC, &c->x86_capability);
+#endif
 		}
 		break;
 
@@ -1453,7 +1463,7 @@
 		tmp = (!(dir0_lsn & 7) || dir0_lsn & 1) ? 2 : 0;
 		Cx86_cb[tmp] = cyrix_model_mult2[dir0_lsn & 7];
 		p = Cx86_cb+tmp;
-        	if (((dir1 & 0x0f) > 4) || ((dir1 & 0xf0) == 0x20))
+	 	if (((dir1 & 0x0f) > 4) || ((dir1 & 0xf0) == 0x20))
 			(c->x86_model)++;
 		/* Emulate MTRRs using Cyrix's ARRs. */
 		set_bit(X86_FEATURE_CYRIX_ARR, &c->x86_capability);
@@ -2096,7 +2106,7 @@
 		}
 		if ( l1i || l1d )
 			printk(KERN_INFO "CPU: L1 I cache: %dK, L1 D cache: %dK\n",
-			       l1i, l1d);
+			      l1i, l1d);
 		if ( l2 )
 			printk(KERN_INFO "CPU: L2 cache: %dK\n", l2);
 		if ( l3 )
@@ -2203,6 +2213,8 @@
 		c->x86_vendor = X86_VENDOR_AMD;
 	else if (!strcmp(v, "CyrixInstead"))
 		c->x86_vendor = X86_VENDOR_CYRIX;
+	else if (!strcmp(v, "Geode by NSC"))
+		c->x86_vendor = X86_VENDOR_NSC;
 	else if (!strcmp(v, "UMC UMC UMC "))
 		c->x86_vendor = X86_VENDOR_UMC;
 	else if (!strcmp(v, "CentaurHauls"))
@@ -2528,6 +2540,38 @@
 	 * indicate the features this CPU genuinely supports!
 	 */
 	switch ( c->x86_vendor ) {
+	case X86_VENDOR_AMD:
+		init_amd(c);
+		break;
+
+	case X86_VENDOR_CENTAUR:
+		init_centaur(c);
+		break;
+
+	case X86_VENDOR_CYRIX:
+		init_cyrix(c);
+		break;
+
+	case X86_VENDOR_INTEL:
+		init_intel(c);
+		break;
+
+	case X86_VENDOR_NEXGEN:
+		c->x86_cache_size = 256; /* A few had 1 MB... */
+		break;
+
+	case X86_VENDOR_NSC:
+        init_cyrix(c);
+		break;
+
+	case X86_VENDOR_RISE:
+		init_rise(c);
+		break;
+
+	case X86_VENDOR_TRANSMETA:
+		init_transmeta(c);
+		break;
+
 	case X86_VENDOR_UNKNOWN:
 	default:
 		/* Not much we can do here... */
@@ -2542,33 +2586,6 @@
 		}
 		break;
 
-	case X86_VENDOR_CYRIX:
-		init_cyrix(c);
-		break;
-
-	case X86_VENDOR_AMD:
-		init_amd(c);
-		break;
-
-	case X86_VENDOR_CENTAUR:
-		init_centaur(c);
-		break;
-
-	case X86_VENDOR_INTEL:
-		init_intel(c);
-		break;
-
-	case X86_VENDOR_NEXGEN:
-		c->x86_cache_size = 256; /* A few had 1 MB... */
-		break;
-
-	case X86_VENDOR_TRANSMETA:
-		init_transmeta(c);
-		break;
-
-	case X86_VENDOR_RISE:
-		init_rise(c);
-		break;
 	}
 
 	printk(KERN_DEBUG "CPU: After vendor init, caps: %08x %08x %08x %08x\n",
@@ -2646,14 +2663,15 @@
 {
 	get_cpu_vendor(&boot_cpu_data);
 
-	if ( boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX )
+	if (( boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX ) ||
+	    ( boot_cpu_data.x86_vendor == X86_VENDOR_NSC   ))
 		init_cyrix(&boot_cpu_data);
 }
 
 
 /* These need to match <asm/processor.h> */
 static char *cpu_vendor_names[] __initdata = {
-	"Intel", "Cyrix", "AMD", "UMC", "NexGen", "Centaur", "Rise", "Transmeta" };
+	"Intel", "Cyrix", "AMD", "UMC", "NexGen", "Centaur", "Rise", "Transmeta", "NSC" };
 
 
 void __init print_cpu_info(struct cpuinfo_x86 *c)
@@ -2694,10 +2712,10 @@
 	 */
 	static char *x86_cap_flags[] = {
 		/* Intel-defined */
-	        "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
-	        "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
-	        "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
-	        "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", NULL,
+		"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
+		"cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
+		"pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
+		"fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", NULL,
 
 		/* AMD-defined */
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index a5349ba..ad8aa37 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -25,6 +25,10 @@
 #include <linux/interrupt.h>
 #include <linux/highmem.h>
 
+#ifdef CONFIG_EISA
+#include <linux/ioport.h>
+#endif
+
 #ifdef CONFIG_MCA
 #include <linux/mca.h>
 #include <asm/processor.h>
@@ -951,11 +955,20 @@
 	printk("Cobalt APIC enabled: ID reg %lx\n", co_apic_read(CO_APIC_ID));
 }
 #endif
+
+#ifdef CONFIG_EISA
+int EISA_bus;
+static struct resource eisa_id = { "EISA ID", 0xc80, 0xc83, IORESOURCE_BUSY };
+#endif
+
 void __init trap_init(void)
 {
 #ifdef CONFIG_EISA
-	if (isa_readl(0x0FFFD9) == 'E'+('I'<<8)+('S'<<16)+('A'<<24))
+	if (isa_readl(0x0FFFD9) == 'E'+('I'<<8)+('S'<<16)+('A'<<24)) {
 		EISA_bus = 1;
+		if (request_resource(&ioport_resource, &eisa_id) == -EBUSY)
+			printk ("EISA port was EBUSY :-(\n");
+	}
 #endif
 
 #ifdef CONFIG_X86_LOCAL_APIC
diff --git a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
index 043acca..70efe38 100644
--- a/arch/i386/mm/ioremap.c
+++ b/arch/i386/mm/ioremap.c
@@ -11,6 +11,7 @@
 #include <linux/vmalloc.h>
 #include <asm/io.h>
 #include <asm/pgalloc.h>
+#include <asm/fixmap.h>
 
 static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
 	unsigned long phys_addr, unsigned long flags)
@@ -162,7 +163,6 @@
 		return vfree((void *) (PAGE_MASK & (unsigned long) addr));
 }
 
-#include <asm/fixmap.h>
 void __init *bt_ioremap(unsigned long phys_addr, unsigned long size)
 {
 	unsigned long offset, last_addr;
diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c
index fb2a770..c2964682 100644
--- a/arch/ia64/kernel/ia64_ksyms.c
+++ b/arch/ia64/kernel/ia64_ksyms.c
@@ -23,7 +23,6 @@
 EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strpbrk);
 
 #include <linux/irq.h>
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index b96532af..54c73f1 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -205,14 +205,16 @@
     char switches[len+1];
     char *p;
     int ovsc_shift;
+    char *args = switches;
 
-    /* copy string to local array, strtok works destructively... */
+    /* copy string to local array, strsep works destructively... */
     strncpy( switches, str, len );
     switches[len] = 0;
     atari_switches = 0;
 
     /* parse the options */
-    for( p = strtok( switches, "," ); p; p = strtok( NULL, "," ) ) {
+    while ((p = strsep(&args, ",")) != NULL) {
+	if (!*p) continue;
 	ovsc_shift = 0;
 	if (strncmp( p, "ov_", 3 ) == 0) {
 	    p += 3;
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
index 4e980de..3efad5a 100644
--- a/arch/m68k/kernel/m68k_ksyms.c
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -54,7 +54,6 @@
 EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(enable_irq);
 EXPORT_SYMBOL(disable_irq);
 EXPORT_SYMBOL(kernel_thread);
diff --git a/arch/m68k/mac/baboon.c b/arch/m68k/mac/baboon.c
index 9b9bab2..e80793a 100644
--- a/arch/m68k/mac/baboon.c
+++ b/arch/m68k/mac/baboon.c
@@ -27,7 +27,7 @@
 
 void baboon_irq(int, void *, struct pt_regs *);
 
-extern int macide_ack_intr(ide_hwif_t *);
+extern int macide_ack_intr(struct ata_channel *);
 
 /*
  * Baboon initialization.
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
index c2322793..8433873 100644
--- a/arch/mips/kernel/mips_ksyms.c
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -51,7 +51,6 @@
 EXPORT_SYMBOL_NOVERS(memset);
 EXPORT_SYMBOL_NOVERS(memcpy);
 EXPORT_SYMBOL_NOVERS(memmove);
-EXPORT_SYMBOL(simple_strtol);
 EXPORT_SYMBOL_NOVERS(strcat);
 EXPORT_SYMBOL_NOVERS(strchr);
 EXPORT_SYMBOL_NOVERS(strlen);
@@ -60,7 +59,7 @@
 EXPORT_SYMBOL_NOVERS(strnlen);
 EXPORT_SYMBOL_NOVERS(strrchr);
 EXPORT_SYMBOL_NOVERS(strstr);
-EXPORT_SYMBOL_NOVERS(strtok);
+EXPORT_SYMBOL_NOVERS(strsep);
 
 EXPORT_SYMBOL(_clear_page);
 EXPORT_SYMBOL(enable_irq);
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 5a05734..b5ad2cc 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -204,7 +204,7 @@
 #define restore_gp_reg(i) do {						\
 	err |= __get_user(reg, &sc->sc_regs[i]);			\
 	regs->regs[i] = reg;						\
-} while(0);
+} while(0)
 	restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
 	restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
 	restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index a82e0b9..9ea43d1 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -156,7 +156,7 @@
 		sprintf(p->comm, "%s%d", "Idle", i);
 		init_tasks[i] = p;
 		p->processor = i;
-		p->cpus_runnable = 1 << i; /* we schedule the first task manually *
+		p->cpus_runnable = 1 << i; /* we schedule the first task manually */
 		del_from_runqueue(p);
 		unhash_process(p);
 		/* Attach to the address space of init_task. */
diff --git a/arch/mips/sni/pci.c b/arch/mips/sni/pci.c
index 00a3d18..0803242 100644
--- a/arch/mips/sni/pci.c
+++ b/arch/mips/sni/pci.c
@@ -25,7 +25,7 @@
 		 ((dev->bus->number    & 0xff) << 0x10) |                    \
 	         ((dev->devfn & 0xff) << 0x08) |                             \
 	         (where  & 0xfc);                                            \
-} while(0);
+} while(0)
 
 #if 0
 /* To do:  Bring this uptodate ...  */
diff --git a/arch/mips64/kernel/mips64_ksyms.c b/arch/mips64/kernel/mips64_ksyms.c
index 91f18e5..da8d6ed 100644
--- a/arch/mips64/kernel/mips64_ksyms.c
+++ b/arch/mips64/kernel/mips64_ksyms.c
@@ -48,14 +48,13 @@
 EXPORT_SYMBOL_NOVERS(memset);
 EXPORT_SYMBOL_NOVERS(memcpy);
 EXPORT_SYMBOL_NOVERS(memmove);
-EXPORT_SYMBOL(simple_strtol);
 EXPORT_SYMBOL_NOVERS(strcat);
 EXPORT_SYMBOL_NOVERS(strchr);
 EXPORT_SYMBOL_NOVERS(strlen);
 EXPORT_SYMBOL_NOVERS(strncat);
 EXPORT_SYMBOL_NOVERS(strnlen);
 EXPORT_SYMBOL_NOVERS(strrchr);
-EXPORT_SYMBOL_NOVERS(strtok);
+EXPORT_SYMBOL_NOVERS(strsep);
 EXPORT_SYMBOL_NOVERS(strpbrk);
 
 EXPORT_SYMBOL(_clear_page);
diff --git a/arch/mips64/math-emu/cp1emu.c b/arch/mips64/math-emu/cp1emu.c
index 5acd218..dac6494 100644
--- a/arch/mips64/math-emu/cp1emu.c
+++ b/arch/mips64/math-emu/cp1emu.c
@@ -29,7 +29,7 @@
  * Notes: 
  *  1) the IEEE754 library (-le) performs the actual arithmetic;
  *  2) if you know that you won't have an fpu, then you'll get much 
- *     better performance by compiling with -msoft-float!  */
+ *     better performance by compiling with -msoft-float!
  *
  *  Nov 7, 2000
  *  Massive changes to integrate with Linux kernel.
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
index 2b4dbd7..111a2fb 100644
--- a/arch/parisc/kernel/parisc_ksyms.c
+++ b/arch/parisc/kernel/parisc_ksyms.c
@@ -20,7 +20,6 @@
 EXPORT_SYMBOL(strncat);
 EXPORT_SYMBOL(strncmp);
 EXPORT_SYMBOL(strncpy);
-EXPORT_SYMBOL(strtok);
 
 #include <linux/pci.h>
 EXPORT_SYMBOL(hppa_dma_ops);
diff --git a/arch/ppc/4xx_io/stb_kb.c b/arch/ppc/4xx_io/stb_kb.c
index f723e28..ccb2cd8 100644
--- a/arch/ppc/4xx_io/stb_kb.c
+++ b/arch/ppc/4xx_io/stb_kb.c
@@ -19,7 +19,7 @@
 #include <linux/random.h>
 #include <linux/poll.h>
 #include <linux/miscdevice.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/kbd_kern.h>
 
 /* the following are borrowed from pc_keyb.c, thanks to those involved! */
diff --git a/arch/ppc/iSeries/iSeries_irq.c b/arch/ppc/iSeries/iSeries_irq.c
index c0760bc..1d8efc9 100644
--- a/arch/ppc/iSeries/iSeries_irq.c
+++ b/arch/ppc/iSeries/iSeries_irq.c
@@ -36,7 +36,7 @@
 
 #include <linux/irq.h>
 #include <linux/spinlock.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #include <asm/iSeries/HvCallPci.h>
 #include <asm/iSeries/HvCallXm.h>
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 1f45d57..f2591a7 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -123,7 +123,6 @@
 EXPORT_SYMBOL(strchr);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strpbrk);
-EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strlen);
 EXPORT_SYMBOL(strnlen);
diff --git a/arch/ppc/math-emu/op-4.h b/arch/ppc/math-emu/op-4.h
index 3458d78..5da9921 100644
--- a/arch/ppc/math-emu/op-4.h
+++ b/arch/ppc/math-emu/op-4.h
@@ -279,7 +279,7 @@
     X##_f[1] = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE);   \
     X##_f[2] = (rsize <= 2*_FP_W_TYPE_SIZE ? 0 : r >> 2*_FP_W_TYPE_SIZE); \
     X##_f[3] = (rsize <= 3*_FP_W_TYPE_SIZE ? 0 : r >> 3*_FP_W_TYPE_SIZE); \
-  } while (0);
+  } while (0)
 
 #define _FP_FRAC_CONV_4_1(dfs, sfs, D, S)                               \
    do {                                                                 \
diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c
index 617db28..e286bdd 100644
--- a/arch/s390/kernel/s390_ksyms.c
+++ b/arch/s390/kernel/s390_ksyms.c
@@ -44,7 +44,7 @@
 EXPORT_SYMBOL_NOVERS(strnlen);
 EXPORT_SYMBOL_NOVERS(strrchr);
 EXPORT_SYMBOL_NOVERS(strstr);
-EXPORT_SYMBOL_NOVERS(strtok);
+EXPORT_SYMBOL_NOVERS(strsep);
 EXPORT_SYMBOL_NOVERS(strpbrk);
 
 /*
diff --git a/arch/s390x/kernel/s390_ksyms.c b/arch/s390x/kernel/s390_ksyms.c
index 5b94151..edfb5f6 100644
--- a/arch/s390x/kernel/s390_ksyms.c
+++ b/arch/s390x/kernel/s390_ksyms.c
@@ -47,7 +47,7 @@
 EXPORT_SYMBOL_NOVERS(strnlen);
 EXPORT_SYMBOL_NOVERS(strrchr);
 EXPORT_SYMBOL_NOVERS(strstr);
-EXPORT_SYMBOL_NOVERS(strtok);
+EXPORT_SYMBOL_NOVERS(strsep);
 EXPORT_SYMBOL_NOVERS(strpbrk);
 
 /*
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index 40c5936d..6ef33a1 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -39,9 +39,6 @@
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial_copy);
 
-EXPORT_SYMBOL(simple_strtol);
-
-EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strlen);
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 8f4c425..e7ff970 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -161,7 +161,7 @@
 static void *_sparc_alloc_io(unsigned int busno, unsigned long phys,
     unsigned long size, char *name)
 {
-	static int printed_full = 0;
+	static int printed_full;
 	struct xresource *xres;
 	struct resource *res;
 	char *tack;
diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c
index 5e3a400..0235faa 100644
--- a/arch/sparc/kernel/irq.c
+++ b/arch/sparc/kernel/irq.c
@@ -91,7 +91,7 @@
  */
 #define MAX_STATIC_ALLOC	4
 struct irqaction static_irqaction[MAX_STATIC_ALLOC];
-int static_irq_count = 0;
+int static_irq_count;
 
 struct irqaction *irq_action[NR_IRQS+1] = {
 	  NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL,
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index 53c2aaa2..5bc6a12 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -185,7 +185,7 @@
  * Only one PCIC per IIep,
  * and since we have no SMP IIep, only one per system.
  */
-static int pcic0_up = 0;
+static int pcic0_up;
 static struct linux_pcic pcic0;
 
 unsigned int pcic_regs;
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
index 6d96f8d..0afa247 100644
--- a/arch/sparc/kernel/process.c
+++ b/arch/sparc/kernel/process.c
@@ -63,9 +63,9 @@
 	for (;;) {
 		if (ARCH_SUN4C_SUN4) {
 			static int count = HZ;
-			static unsigned long last_jiffies = 0;
-			static unsigned long last_faults = 0;
-			static unsigned long fps = 0;
+			static unsigned long last_jiffies;
+			static unsigned long last_faults;
+			static unsigned long fps;
 			unsigned long now;
 			unsigned long faults;
 			unsigned long flags;
@@ -83,7 +83,7 @@
 				fps = (fps + (faults - last_faults)) >> 1;
 				last_faults = faults;
 #if 0
-				printk("kernel faults / second = %d\n", fps);
+				printk("kernel faults / second = %ld\n", fps);
 #endif
 				if (fps >= SUN4C_FAULT_HIGH) {
 					sun4c_grow_kernel_ring();
diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c
index 8b85b4f..1d30b5c8 100644
--- a/arch/sparc/kernel/ptrace.c
+++ b/arch/sparc/kernel/ptrace.c
@@ -278,6 +278,7 @@
 	unsigned long data = regs->u_regs[UREG_I3];
 	unsigned long addr2 = regs->u_regs[UREG_I4];
 	struct task_struct *child;
+	int ret;
 
 	lock_kernel();
 #ifdef DEBUG_PTRACE
@@ -335,20 +336,13 @@
 		pt_succ_return(regs, 0);
 		goto out_tsk;
 	}
-	if (!(child->ptrace & PT_PTRACED)) {
-		pt_error_return(regs, ESRCH);
+
+	ret = ptrace_check_attach(child, request == PTRACE_KILL);
+	if (ret < 0) {
+		pt_error_return(regs, -ret);
 		goto out_tsk;
 	}
-	if(child->state != TASK_STOPPED) {
-		if(request != PTRACE_KILL) {
-			pt_error_return(regs, ESRCH);
-			goto out_tsk;
-		}
-	}
-	if(child->p_pptr != current) {
-		pt_error_return(regs, ESRCH);
-		goto out_tsk;
-	}
+
 	switch(request) {
 	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
 	case PTRACE_PEEKDATA: {
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c
index 89fbafc..09b9230 100644
--- a/arch/sparc/kernel/setup.c
+++ b/arch/sparc/kernel/setup.c
@@ -47,8 +47,6 @@
 #include <asm/hardirq.h>
 #include <asm/machines.h>
 
-#undef PROM_DEBUG_CONSOLE
-
 struct screen_info screen_info = {
 	0, 0,			/* orig-x, orig-y */
 	0,			/* unused */
@@ -134,6 +132,19 @@
 	}
 }
 
+static void
+prom_console_write(struct console *con, const char *s, unsigned n)
+{
+	prom_printf("%s", s);
+}
+
+static struct console prom_debug_console = {
+	name:		"debug",
+	write:		prom_console_write,
+	flags:		CON_PRINTBUFFER,
+	index:		-1,
+};
+
 int obp_system_intr(void)
 {
 	if (boot_flags & BOOTME_KGDB) {
@@ -166,6 +177,10 @@
 		prom_printf("boot_flags_init: Halt!\n");
 		prom_halt();
 		break;
+	case 'p':
+		/* Use PROM debug console. */
+		register_console(&prom_debug_console);
+		break;
 	default:
 		printk("Unknown boot switch (-%c)\n", c);
 		break;
@@ -280,21 +295,6 @@
 
 struct pt_regs fake_swapper_regs;
 
-#ifdef PROM_DEBUG_CONSOLE
-static void
-prom_console_write(struct console *con, const char *s, unsigned n)
-{
-	prom_printf("%s", s);
-}
-
-static struct console prom_console = {
-	name:		"debug",
-	write:		prom_console_write,
-	flags:		CON_PRINTBUFFER,
-	index:		-1,
-};
-#endif
-
 extern void paging_init(void);
 
 void __init setup_arch(char **cmdline_p)
@@ -348,9 +348,6 @@
 		printk("UNKNOWN!\n");
 		break;
 	};
-#ifdef PROM_DEBUG_CONSOLE
-	register_console(&prom_console);
-#endif
 
 #ifdef CONFIG_DUMMY_CONSOLE
 	conswitchp = &dummy_con;
@@ -381,7 +378,7 @@
 	if (!root_flags)
 		root_mountflags &= ~MS_RDONLY;
 	ROOT_DEV = to_kdev_t(root_dev);
-#ifdef CONFIG_BLK_DEV_RAM
+#ifdef CONFIG_BLK_DEV_INITRD
 	rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK;
 	rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0);
 	rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);	
diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c
index 08ad962..022883f 100644
--- a/arch/sparc/kernel/signal.c
+++ b/arch/sparc/kernel/signal.c
@@ -1195,8 +1195,8 @@
 				info.si_signo = signr;
 				info.si_errno = 0;
 				info.si_code = SI_USER;
-				info.si_pid = current->p_pptr->pid;
-				info.si_uid = current->p_pptr->uid;
+				info.si_pid = current->parent->pid;
+				info.si_uid = current->parent->uid;
 			}
 
 			/* If the (new) signal is now blocked, requeue it.  */
@@ -1245,7 +1245,7 @@
 				current->exit_code = signr;
 
 				/* notify_parent() is SMP safe */
-				if(!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags &
+				if(!(current->parent->sig->action[SIGCHLD-1].sa.sa_flags &
 				     SA_NOCLDSTOP))
 					notify_parent(current, SIGCHLD);
 				schedule();
@@ -1280,7 +1280,10 @@
 #endif
 				/* fall through */
 			default:
-				sig_exit(signr, exit_code, &info);
+				sigaddset(&current->pending.signal, signr);
+				recalc_sigpending(current);
+				current->flags |= PF_SIGNALED;
+				do_exit(exit_code);
 				/* NOT REACHED */
 			}
 		}
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index 25b97dd..316fc96 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -250,7 +250,6 @@
 EXPORT_SYMBOL(strchr);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strpbrk);
-EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(page_kernel);
 
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index 46e199a..4c2dd85 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -47,7 +47,7 @@
 extern volatile int smp_processors_ready;
 extern unsigned long cpu_present_map;
 extern int smp_num_cpus;
-static int smp_highest_cpu = 0;
+static int smp_highest_cpu;
 extern int smp_threads_ready;
 extern unsigned char mid_xlate[NR_CPUS];
 extern volatile unsigned long cpu_callin_map[NR_CPUS];
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
index 8e40a70..6e7935a 100644
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -115,7 +115,7 @@
 void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	/* last time the cmos clock got updated */
-	static long last_rtc_update=0;
+	static long last_rtc_update;
 
 #ifndef CONFIG_SMP
 	if(!user_mode(regs))
diff --git a/arch/sparc/kernel/traps.c b/arch/sparc/kernel/traps.c
index 5c361f9..2bdaa11 100644
--- a/arch/sparc/kernel/traps.c
+++ b/arch/sparc/kernel/traps.c
@@ -272,7 +272,7 @@
 void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
 		 unsigned long psr)
 {
-	static int calls = 0;
+	static int calls;
 	siginfo_t info;
 	unsigned long fsr;
 	int ret = 0;
diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c
index cfd35db..927a72e 100644
--- a/arch/sparc/mm/iommu.c
+++ b/arch/sparc/mm/iommu.c
@@ -25,7 +25,7 @@
 BTFIXUPDEF_CALL(void, flush_page_for_dma, unsigned long)
 #define flush_page_for_dma(page) BTFIXUP_CALL(flush_page_for_dma)(page)
 extern int flush_page_for_dma_global;
-static int viking_flush = 0;
+static int viking_flush;
 /* viking.S */
 extern void viking_flush_page(unsigned long page);
 extern void viking_mxcc_flush_page(unsigned long page);
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index 6f5fa8c..bd02921 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -1739,7 +1739,7 @@
 static void __init poke_viking(void)
 {
 	unsigned long mreg = srmmu_get_mmureg();
-	static int smp_catch = 0;
+	static int smp_catch;
 
 	if(viking_mxcc_present) {
 		unsigned long mxcc_control = mxcc_get_creg();
@@ -1963,7 +1963,7 @@
 		iaddr = &(insn); \
 		daddr = &(dest); \
 		*iaddr = SPARC_BRANCH((unsigned long) daddr, (unsigned long) iaddr); \
-	} while(0);
+	} while(0)
 
 static void __init patch_window_trap_handlers(void)
 {
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
index f063840..6583630 100644
--- a/arch/sparc/mm/sun4c.c
+++ b/arch/sparc/mm/sun4c.c
@@ -425,7 +425,7 @@
 		daddr = &(dst);		\
 		iaddr = &(src);		\
 		*daddr = *iaddr;	\
-	} while (0);
+	} while (0)
 
 static void patch_kernel_fault_handler(void)
 {
diff --git a/arch/sparc/mm/swift.S b/arch/sparc/mm/swift.S
index b1acc2b..2dcaa5a 100644
--- a/arch/sparc/mm/swift.S
+++ b/arch/sparc/mm/swift.S
@@ -53,11 +53,9 @@
 
 	.globl	swift_flush_cache_mm
 swift_flush_cache_mm:
-#ifndef CONFIG_SMP
 	ld	[%o0 + AOFF_mm_context], %g2
 	cmp	%g2, -1
 	be	swift_flush_cache_mm_out
-#endif
 	WINDOW_FLUSH(%g4, %g5)
 	rd	%psr, %g1
 	andn	%g1, PSR_ET, %g3
@@ -121,11 +119,9 @@
 swift_flush_cache_page:
 	ld	[%o0 + 0x0], %o0		/* XXX vma->vm_mm, GROSS XXX */
 70:
-#ifndef CONFIG_SMP
 	ld	[%o0 + AOFF_mm_context], %g2
 	cmp	%g2, -1
 	be	swift_flush_cache_page_out
-#endif
 	WINDOW_FLUSH(%g4, %g5)
 	rd	%psr, %g1
 	andn	%g1, PSR_ET, %g3
@@ -226,11 +222,9 @@
 swift_flush_tlb_range:
 	ld	[%o0 + 0x00], %o0	/* XXX vma->vm_mm GROSS XXX */
 swift_flush_tlb_mm:
-#ifndef CONFIG_SMP
 	ld	[%o0 + AOFF_mm_context], %g2
 	cmp	%g2, -1
 	be	swift_flush_tlb_all_out
-#endif
 swift_flush_tlb_all:
 	mov	0x400, %o1
 	sta	%g0, [%o1] ASI_M_FLUSH_PROBE
@@ -244,11 +238,9 @@
 	mov	SRMMU_CTX_REG, %g1
 	ld	[%o0 + AOFF_mm_context], %o3
 	andn	%o1, (PAGE_SIZE - 1), %o1
-#ifndef CONFIG_SMP
 	cmp	%o3, -1
 	be	swift_flush_tlb_page_out
 	 nop
-#endif
 #if 1
 	mov	0x400, %o1
 	sta	%g0, [%o1] ASI_M_FLUSH_PROBE	
diff --git a/arch/sparc/mm/tsunami.S b/arch/sparc/mm/tsunami.S
index 5d490af..5cf689a 100644
--- a/arch/sparc/mm/tsunami.S
+++ b/arch/sparc/mm/tsunami.S
@@ -27,10 +27,8 @@
 	ld	[%o0 + 0x0], %o0	/* XXX vma->vm_mm, GROSS XXX */
 tsunami_flush_cache_mm:
 	ld	[%o0 + AOFF_mm_context], %g2
-#ifndef CONFIG_SMP
 	cmp	%g2, -1
 	be	tsunami_flush_cache_out
-#endif
 tsunami_flush_cache_all:
 	WINDOW_FLUSH(%g4, %g5)
 tsunami_flush_page_for_dma:
@@ -50,11 +48,9 @@
 tsunami_flush_tlb_range:
 	ld	[%o0 + 0x00], %o0	/* XXX vma->vm_mm GROSS XXX */
 tsunami_flush_tlb_mm:
-#ifndef CONFIG_SMP
 	ld	[%o0 + AOFF_mm_context], %g2
 	cmp	%g2, -1
 	be	tsunami_flush_tlb_out
-#endif
 tsunami_flush_tlb_all:
 	 mov	0x400, %o1
 	sta	%g0, [%o1] ASI_M_FLUSH_PROBE
@@ -73,10 +69,8 @@
 	mov	SRMMU_CTX_REG, %g1
 	ld	[%o0 + AOFF_mm_context], %o3
 	andn	%o1, (PAGE_SIZE - 1), %o1
-#ifndef CONFIG_SMP
 	cmp	%o3, -1
 	be	tsunami_flush_tlb_page_out
-#endif
 	 lda	[%g1] ASI_M_MMUREGS, %g5
 	sta	%o3, [%g1] ASI_M_MMUREGS
 	sta	%g0, [%o1] ASI_M_FLUSH_PROBE
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 98b73d9..472ab2d 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -248,7 +248,7 @@
 CONFIG_IDE=y
 
 #
-# IDE, ATA and ATAPI Block devices
+# ATA and ATAPI Block devices
 #
 CONFIG_BLK_DEV_IDE=y
 
@@ -283,9 +283,9 @@
 # CONFIG_BLK_DEV_ISAPNP is not set
 # CONFIG_BLK_DEV_RZ1000 is not set
 CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
 # CONFIG_IDEPCI_SHARE_IRQ is not set
 CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_IDEDMA_PCI_AUTO=y
 CONFIG_IDEDMA_ONLYDISK=y
 CONFIG_BLK_DEV_IDEDMA=y
@@ -296,13 +296,13 @@
 CONFIG_BLK_DEV_ALI15X3=y
 # CONFIG_WDC_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD74XX is not set
-# CONFIG_AMD74XX_OVERRIDE is not set
 CONFIG_BLK_DEV_CMD64X=y
 # CONFIG_BLK_DEV_CY82C693 is not set
 # CONFIG_BLK_DEV_CS5530 is not set
 # CONFIG_BLK_DEV_HPT34X is not set
 # CONFIG_HPT34X_AUTODMA is not set
 # CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_PIIX is not set
 CONFIG_BLK_DEV_NS87415=y
 # CONFIG_BLK_DEV_OPTI621 is not set
 # CONFIG_BLK_DEV_PDC_ADMA is not set
@@ -314,10 +314,9 @@
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
 # CONFIG_IDE_CHIPSETS is not set
-CONFIG_IDEDMA_AUTO=y
 # CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
 # CONFIG_DMA_NONPCI is not set
-CONFIG_BLK_DEV_IDE_MODES=y
 # CONFIG_BLK_DEV_ATARAID is not set
 # CONFIG_BLK_DEV_ATARAID_PDC is not set
 # CONFIG_BLK_DEV_ATARAID_HPT is not set
@@ -789,6 +788,7 @@
 # USB Device Class drivers
 #
 # CONFIG_USB_AUDIO is not set
+# CONFIG_USB_EMI26 is not set
 CONFIG_USB_BLUETOOTH=m
 CONFIG_USB_STORAGE=m
 # CONFIG_USB_STORAGE_DEBUG is not set
@@ -909,6 +909,7 @@
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_DCFLUSH is not set
+# CONFIG_STACK_DEBUG is not set
 
 #
 # Library routines
diff --git a/arch/sparc64/kernel/binfmt_elf32.c b/arch/sparc64/kernel/binfmt_elf32.c
index 5b742bc..cbe01f5 100644
--- a/arch/sparc64/kernel/binfmt_elf32.c
+++ b/arch/sparc64/kernel/binfmt_elf32.c
@@ -43,7 +43,7 @@
 	dest[34] = (unsigned int) src->tnpc;		\
 	dest[35] = src->y;				\
 	dest[36] = dest[37] = 0; /* XXX */		\
-} while(0);
+} while(0)
 
 typedef struct {
 	union {
diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c
index 2ccb403..a01ecbd 100644
--- a/arch/sparc64/kernel/ebus.c
+++ b/arch/sparc64/kernel/ebus.c
@@ -275,6 +275,25 @@
 	printk("]");
 }
 
+static struct pci_dev *find_next_ebus(struct pci_dev *start, int *is_rio_p)
+{
+	struct pci_dev *pdev = start;
+
+	do {
+		pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_ANY_ID, pdev);
+		if (pdev &&
+		    (pdev->device == PCI_DEVICE_ID_SUN_EBUS ||
+		     pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS))
+			break;
+	} while (pdev != NULL);
+
+	if (pdev && (pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS))
+		*is_rio_p = 1;
+	else
+		*is_rio_p = 0;
+
+	return pdev;
+}
 
 void __init ebus_init(void)
 {
@@ -289,12 +308,7 @@
 	if (!pci_present())
 		return;
 
-	is_rio = 0;
-	pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, 0);
-	if (!pdev) {
-		pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_RIO_EBUS, 0);
-		is_rio = 1;
-	}
+	pdev = find_next_ebus(NULL, &is_rio);
 	if (!pdev) {
 		printk("ebus: No EBus's found.\n");
 		return;
@@ -315,16 +329,7 @@
 		   we'd have to tweak with the ebus_chain
 		   in the runtime after initialization. -jj */
 		if (!prom_getchild (ebusnd)) {
-			struct pci_dev *orig_pdev = pdev;
-
-			is_rio = 0;
-			pdev = pci_find_device(PCI_VENDOR_ID_SUN, 
-					       PCI_DEVICE_ID_SUN_EBUS, orig_pdev);
-			if (!pdev) {
-				pdev = pci_find_device(PCI_VENDOR_ID_SUN, 
-						       PCI_DEVICE_ID_SUN_RIO_EBUS, orig_pdev);
-				is_rio = 1;
-			}
+			pdev = find_next_ebus(pdev, &is_rio);
 			if (!pdev) {
 				if (ebus == ebus_chain) {
 					ebus_chain = NULL;
@@ -374,20 +379,9 @@
 	next_ebus:
 		printk("\n");
 
-		{
-			struct pci_dev *orig_pdev = pdev;
-
-			is_rio = 0;
-			pdev = pci_find_device(PCI_VENDOR_ID_SUN,
-					       PCI_DEVICE_ID_SUN_EBUS, orig_pdev);
-			if (!pdev) {
-				pdev = pci_find_device(PCI_VENDOR_ID_SUN,
-						       PCI_DEVICE_ID_SUN_RIO_EBUS, orig_pdev);
-				is_rio = 1;
-			}
-			if (!pdev)
-				break;
-		}
+		pdev = find_next_ebus(pdev, &is_rio);
+		if (!pdev)
+			break;
 
 		cookie = pdev->sysdata;
 		ebusnd = cookie->prom_node;
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index d7962d7..6ada277 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -565,13 +565,6 @@
 #define KERN_HIGHBITS		((_PAGE_VALID|_PAGE_SZ4MB)^0xfffff80000000000)
 #define KERN_LOWBITS		(_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
 
-#define VPTE_BASE_SPITFIRE	0xfffffffe00000000
-#if 1
-#define VPTE_BASE_CHEETAH	VPTE_BASE_SPITFIRE
-#else
-#define VPTE_BASE_CHEETAH	0xffe0000000000000
-#endif
-
 	mov	TSB_REG, %g1
 	stxa	%g0, [%g1] ASI_DMMU
 	membar	#Sync
@@ -602,8 +595,6 @@
 	clr	%g7
 #undef KERN_HIGHBITS
 #undef KERN_LOWBITS
-#undef VPTE_BASE_SPITFIRE
-#undef VPTE_BASE_CHEETAH
 
 	/* Setup Interrupt globals */
 	wrpr	%o1, (PSTATE_IG|PSTATE_IE), %pstate
diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
index f979f3f..d6763ae 100644
--- a/arch/sparc64/kernel/ioctl32.c
+++ b/arch/sparc64/kernel/ioctl32.c
@@ -1061,7 +1061,7 @@
 		break;
 	default:
 		do {
-			static int count = 0;
+			static int count;
 			if (++count <= 20)
 				printk("%s: Unknown fb ioctl cmd fd(%d) "
 				       "cmd(%08x) arg(%08lx)\n",
@@ -1714,7 +1714,7 @@
 		break;
 	default:
 		do {
-			static int count = 0;
+			static int count;
 			if (++count <= 20)
 				printk("ppp_ioctl: Unknown cmd fd(%d) "
 				       "cmd(%08x) arg(%08x)\n",
@@ -1824,7 +1824,7 @@
 		break;
 	default:
 		do {
-			static int count = 0;
+			static int count;
 			if (++count <= 20)
 				printk("mt_ioctl: Unknown cmd fd(%d) "
 				       "cmd(%08x) arg(%08x)\n",
@@ -1942,7 +1942,7 @@
 		break;
 	default:
 		do {
-			static int count = 0;
+			static int count;
 			if (++count <= 20)
 				printk("cdrom_ioctl: Unknown cmd fd(%d) "
 				       "cmd(%08x) arg(%08x)\n",
@@ -2029,7 +2029,7 @@
 		}
 		break;
 	default: {
-		static int count = 0;
+		static int count;
 		if (++count <= 20)
 			printk("%s: Unknown loop ioctl cmd, fd(%d) "
 			       "cmd(%08x) arg(%08lx)\n",
@@ -4882,7 +4882,7 @@
 		handler = (void *)(long)t->handler;
 		error = handler(fd, cmd, arg, filp);
 	} else {
-		static int count = 0;
+		static int count;
 		if (++count <= 20)
 			printk("sys32_ioctl(%s:%d): Unknown cmd fd(%d) "
 			       "cmd(%08x) arg(%08x)\n",
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index 59b4f9c..82bca8d 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -82,7 +82,7 @@
  */
 #define MAX_STATIC_ALLOC	4
 static struct irqaction static_irqaction[MAX_STATIC_ALLOC];
-static int static_irq_count = 0;
+static int static_irq_count;
 
 /* This is exported so that fast IRQ handlers can get at it... -DaveM */
 struct irqaction *irq_action[NR_IRQS+1] = {
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index 4507491..bca907b 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -234,33 +234,63 @@
 	return request_resource(root, res);
 }
 
+/*
+ * Given the PCI bus a device resides on, try to
+ * find an acceptable resource allocation for a
+ * specific device resource..
+ */
+static int pci_assign_bus_resource(const struct pci_bus *bus,
+	struct pci_dev *dev,
+	struct resource *res,
+	unsigned long size,
+	unsigned long min,
+	int resno)
+{
+	unsigned int type_mask;
+	int i;
+
+	type_mask = IORESOURCE_IO | IORESOURCE_MEM;
+	for (i = 0 ; i < 4; i++) {
+		struct resource *r = bus->resource[i];
+		if (!r)
+			continue;
+
+		/* type_mask must match */
+		if ((res->flags ^ r->flags) & type_mask)
+			continue;
+
+		/* Ok, try it out.. */
+		if (allocate_resource(r, res, size, min, -1, size, NULL, NULL) < 0)
+			continue;
+
+		/* PCI config space updated by caller.  */
+		return 0;
+	}
+	return -EBUSY;
+}
+
 int pci_assign_resource(struct pci_dev *pdev, int resource)
 {
 	struct pcidev_cookie *pcp = pdev->sysdata;
 	struct pci_pbm_info *pbm = pcp->pbm;
 	struct resource *res = &pdev->resource[resource];
-	struct resource *root;
-	unsigned long min, max, size, align;
+	unsigned long min, size;
 	int err;
 
-	if (res->flags & IORESOURCE_IO) {
-		root = &pbm->io_space;
-		min = root->start + 0x400UL;
-		max = root->end;
-	} else {
-		root = &pbm->mem_space;
-		min = root->start;
-		max = min + 0x80000000UL;
-	}
+	if (res->flags & IORESOURCE_IO)
+		min = pbm->io_space.start + 0x400UL;
+	else
+		min = pbm->mem_space.start;
 
-	size = res->end - res->start;
-	align = size + 1;
+	size = res->end - res->start + 1;
 
-	err = allocate_resource(root, res, size + 1, min, max, align, NULL, NULL);
+	err = pci_assign_bus_resource(pdev->bus, pdev, res, size, min, resource);
+
 	if (err < 0) {
 		printk("PCI: Failed to allocate resource %d for %s\n",
 		       resource, pdev->name);
 	} else {
+		/* Update PCI config space. */
 		pbm->parent->base_address_update(pdev, resource);
 	}
 
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
index 5b0a721..b7ba835 100644
--- a/arch/sparc64/kernel/pci_common.c
+++ b/arch/sparc64/kernel/pci_common.c
@@ -571,14 +571,12 @@
 	struct pci_pbm_info *pbm = dev_pcp->pbm;
 	struct linux_prom_pci_registers *pregs = dev_pcp->prom_regs;
 	unsigned int hi, mid, lo, irq;
-	int i, num_intmap;
-
-	if (pbm->num_pbm_intmap == 0)
-		return 0;
+	int i, num_intmap, map_slot;
 
 	intmap = &pbm->pbm_intmap[0];
 	intmask = &pbm->pbm_intmask;
 	num_intmap = pbm->num_pbm_intmap;
+	map_slot = 0;
 
 	/* If we are underneath a PCI bridge, use PROM register
 	 * property of the parent bridge which is closest to
@@ -639,11 +637,21 @@
 				printk("pci_intmap_match: Trying to recover.\n");
 				return 0;
 			}
+
+			if (pdev->bus->self != bus_dev)
+				map_slot = 1;
 		} else {
 			pregs = bus_pcp->prom_regs;
+			map_slot = 1;
 		}
 	}
 
+	if (map_slot) {
+		*interrupt = ((*interrupt
+			       - 1
+			       + PCI_SLOT(pdev->devfn)) & 0x3) + 1;
+	}
+
 	hi   = pregs->phys_hi & intmask->phys_hi;
 	mid  = pregs->phys_mid & intmask->phys_mid;
 	lo   = pregs->phys_lo & intmask->phys_lo;
@@ -655,24 +663,33 @@
 		    intmap[i].phys_lo  == lo	&&
 		    intmap[i].interrupt == irq) {
 			*interrupt = intmap[i].cinterrupt;
+			printk("PCI-IRQ: Routing bus[%2x] slot[%2x] map[%d] to INO[%02x]\n",
+			       pdev->bus->number, PCI_SLOT(pdev->devfn),
+			       map_slot, *interrupt);
 			return 1;
 		}
 	}
 
-	/* Print it both to OBP console and kernel one so that if bootup
-	 * hangs here the user has the information to report.
+	/* We will run this code even if pbm->num_pbm_intmap is zero, just so
+	 * we can apply the slot mapping to the PROM interrupt property value.
+	 * So do not spit out these warnings in that case.
 	 */
-	prom_printf("pci_intmap_match: bus %02x, devfn %02x: ",
-		    pdev->bus->number, pdev->devfn);
-	prom_printf("IRQ [%08x.%08x.%08x.%08x] not found in interrupt-map\n",
-		    pregs->phys_hi, pregs->phys_mid, pregs->phys_lo, *interrupt);
-	prom_printf("Please email this information to davem@redhat.com\n");
+	if (num_intmap != 0) {
+		/* Print it both to OBP console and kernel one so that if bootup
+		 * hangs here the user has the information to report.
+		 */
+		prom_printf("pci_intmap_match: bus %02x, devfn %02x: ",
+			    pdev->bus->number, pdev->devfn);
+		prom_printf("IRQ [%08x.%08x.%08x.%08x] not found in interrupt-map\n",
+			    pregs->phys_hi, pregs->phys_mid, pregs->phys_lo, *interrupt);
+		prom_printf("Please email this information to davem@redhat.com\n");
 
-	printk("pci_intmap_match: bus %02x, devfn %02x: ",
-	       pdev->bus->number, pdev->devfn);
-	printk("IRQ [%08x.%08x.%08x.%08x] not found in interrupt-map\n",
-	       pregs->phys_hi, pregs->phys_mid, pregs->phys_lo, *interrupt);
-	printk("Please email this information to davem@redhat.com\n");
+		printk("pci_intmap_match: bus %02x, devfn %02x: ",
+		       pdev->bus->number, pdev->devfn);
+		printk("IRQ [%08x.%08x.%08x.%08x] not found in interrupt-map\n",
+		       pregs->phys_hi, pregs->phys_mid, pregs->phys_lo, *interrupt);
+		printk("Please email this information to davem@redhat.com\n");
+	}
 
 	return 0;
 }
@@ -720,20 +737,6 @@
 		goto have_irq;
 	}
 
-	/* Firmware gets quad-hme interrupts property totally
-	 * wrong.  It is 4 EBUS+HME devices behind a Digital bridge.
-	 * For each of the 4 instances the EBUS has interrupt property
-	 * '1' and the HME has interrupt property '2'.  So we have to
-	 * fix this up.
-	 */
-	if (!strcmp(pcp->prom_name, "SUNW,qfe") ||
-	    !strcmp(pcp->prom_name, "qfe")) {
-		if (PCI_SLOT(pdev->devfn) & ~3)
-			BUG();
-
-		prom_irq = PCI_SLOT(pdev->devfn) + 1;
-	}
-
 	/* Can we find a matching entry in the interrupt-map? */
 	if (pci_intmap_match(pdev, &prom_irq)) {
 		pdev->irq = p->irq_build(pbm, pdev, (portid << 6) | prom_irq);
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
index 7276dd4..3d2230a 100644
--- a/arch/sparc64/kernel/pci_psycho.c
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -1101,7 +1101,14 @@
 	int where, size, is_64bit;
 
 	res = &pdev->resource[resource];
-	where = PCI_BASE_ADDRESS_0 + (resource * 4);
+	if (resource < 6) {
+		where = PCI_BASE_ADDRESS_0 + (resource * 4);
+	} else if (resource == PCI_ROM_RESOURCE) {
+		where = pdev->rom_base_reg;
+	} else {
+		/* Somebody might have asked allocation of a non-standard resource */
+		return;
+	}
 
 	is_64bit = 0;
 	if (res->flags & IORESOURCE_IO)
@@ -1117,6 +1124,10 @@
 	pci_read_config_dword(pdev, where, &reg);
 	reg = ((reg & size) |
 	       (((u32)(res->start - root->start)) & ~size));
+	if (resource == PCI_ROM_RESOURCE) {
+		reg |= PCI_ROM_ADDRESS_ENABLE;
+		res->flags |= PCI_ROM_ADDRESS_ENABLE;
+	}
 	pci_write_config_dword(pdev, where, reg);
 
 	/* This knows that the upper 32-bits of the address
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index 5953791..0de9131 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -1067,7 +1067,14 @@
 	int where, size, is_64bit;
 
 	res = &pdev->resource[resource];
-	where = PCI_BASE_ADDRESS_0 + (resource * 4);
+	if (resource < 6) {
+		where = PCI_BASE_ADDRESS_0 + (resource * 4);
+	} else if (resource == PCI_ROM_RESOURCE) {
+		where = pdev->rom_base_reg;
+	} else {
+		/* Somebody might have asked allocation of a non-standard resource */
+		return;
+	}
 
 	is_64bit = 0;
 	if (res->flags & IORESOURCE_IO)
@@ -1083,6 +1090,10 @@
 	pci_read_config_dword(pdev, where, &reg);
 	reg = ((reg & size) |
 	       (((u32)(res->start - base)) & ~size));
+	if (resource == PCI_ROM_RESOURCE) {
+		reg |= PCI_ROM_ADDRESS_ENABLE;
+		res->flags |= PCI_ROM_ADDRESS_ENABLE;
+	}
 	pci_write_config_dword(pdev, where, reg);
 
 	/* This knows that the upper 32-bits of the address
@@ -1148,7 +1159,7 @@
 
 static void __init sabre_scan_bus(struct pci_controller_info *p)
 {
-	static int once = 0;
+	static int once;
 	struct pci_bus *sabre_bus;
 	struct pci_pbm_info *pbm;
 	struct pcidev_cookie *cookie;
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
index cd604a5..48a81bf 100644
--- a/arch/sparc64/kernel/pci_schizo.c
+++ b/arch/sparc64/kernel/pci_schizo.c
@@ -383,7 +383,7 @@
 	struct ino_bucket *bucket;
 	unsigned long imap, iclr, pbm_off;
 	unsigned long imap_off, iclr_off;
-	int pil, inofixup = 0;
+	int pil;
 
 	if (pbm == &p->pbm_A)
 		pbm_off = SCHIZO_PBM_A_REGS_OFF;
@@ -406,10 +406,13 @@
 	iclr = p->controller_regs + pbm_off + iclr_off;
 	iclr += 4;
 
-	if (ino < 0x18)
-		inofixup = ino & 0x03;
-
-	bucket = __bucket(build_irq(pil, inofixup, iclr, imap));
+	/* On Schizo, no inofixup occurs.  This is because each
+	 * INO has it's own IMAP register.  On Psycho and Sabre
+	 * there is only one IMAP register for each PCI slot even
+	 * though four different INOs can be generated by each
+	 * PCI slot.
+	 */
+	bucket = __bucket(build_irq(pil, 0, iclr, imap));
 	bucket->flags |= IBF_PCI;
 
 	return __irq(bucket);
@@ -1423,7 +1426,14 @@
 	int where, size, is_64bit;
 
 	res = &pdev->resource[resource];
-	where = PCI_BASE_ADDRESS_0 + (resource * 4);
+	if (resource < 6) {
+		where = PCI_BASE_ADDRESS_0 + (resource * 4);
+	} else if (resource == PCI_ROM_RESOURCE) {
+		where = pdev->rom_base_reg;
+	} else {
+		/* Somebody might have asked allocation of a non-standard resource */
+		return;
+	}
 
 	is_64bit = 0;
 	if (res->flags & IORESOURCE_IO)
@@ -1439,6 +1449,10 @@
 	pci_read_config_dword(pdev, where, &reg);
 	reg = ((reg & size) |
 	       (((u32)(res->start - root->start)) & ~size));
+	if (resource == PCI_ROM_RESOURCE) {
+		reg |= PCI_ROM_ADDRESS_ENABLE;
+		res->flags |= PCI_ROM_ADDRESS_ENABLE;
+	}
 	pci_write_config_dword(pdev, where, reg);
 
 	/* This knows that the upper 32-bits of the address
@@ -1469,24 +1483,12 @@
 #define SCHIZO_PCI_B_IO_MATCH		0x00070UL
 #define SCHIZO_PCI_B_IO_MASK		0x00078UL
 
-/* VAL must be non-zero. */
-static unsigned long strip_to_lowest_bit_set(unsigned long val)
-{
-	unsigned long tmp;
-
-	tmp = 1UL;
-	while (!(tmp & val))
-		tmp <<= 1UL;
-
-	return tmp;
-}
-
 static void schizo_determine_mem_io_space(struct pci_pbm_info *pbm,
 					  int is_pbm_a, unsigned long reg_base)
 {
 	u64 mem_match, mem_mask;
 	u64 io_match;
-	u64 long a, b;
+	u64 a;
 
 	if (is_pbm_a) {
 		mem_match = reg_base + SCHIZO_PCI_A_MEM_MATCH;
@@ -1498,11 +1500,12 @@
 	mem_mask = mem_match + 0x8UL;
 
 	a = schizo_read(mem_match) & ~0x8000000000000000UL;
-	b = strip_to_lowest_bit_set(schizo_read(mem_mask));
 
-	/* It should be 2GB in size. */
+	/* It should be 2GB in size but the decode is set for the full
+	 * 4GB so we have to add the 2G by hand.
+	 */
 	pbm->mem_space.start = a;
-	pbm->mem_space.end = a + (b - 1UL);
+	pbm->mem_space.end = a + 0x80000000;
 	pbm->mem_space.flags = IORESOURCE_MEM;
 
 	/* This 32MB area is divided into two pieces.  The first
diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c
index 320fa25..7f7d05b 100644
--- a/arch/sparc64/kernel/power.c
+++ b/arch/sparc64/kernel/power.c
@@ -22,7 +22,7 @@
 #define POWER_COURTESY_OFF (1 << 1)
 
 static DECLARE_WAIT_QUEUE_HEAD(powerd_wait);
-static int button_pressed = 0;
+static int button_pressed;
 
 static void power_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
@@ -81,7 +81,7 @@
 {
 	struct linux_ebus *ebus;
 	struct linux_ebus_device *edev;
-	static int invoked = 0;
+	static int invoked;
 
 	if (invoked)
 		return;
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
index 17efd37..8171a5b 100644
--- a/arch/sparc64/kernel/ptrace.c
+++ b/arch/sparc64/kernel/ptrace.c
@@ -122,6 +122,7 @@
 	unsigned long data = regs->u_regs[UREG_I3];
 	unsigned long addr2 = regs->u_regs[UREG_I4];
 	struct task_struct *child;
+	int ret;
 
 	if (test_thread_flag(TIF_32BIT)) {
 		addr &= 0xffffffffUL;
@@ -184,18 +185,10 @@
 		pt_succ_return(regs, 0);
 		goto out_tsk;
 	}
-	if (!(child->ptrace & PT_PTRACED)) {
-		pt_error_return(regs, ESRCH);
-		goto out_tsk;
-	}
-	if (child->state != TASK_STOPPED) {
-		if (request != PTRACE_KILL) {
-			pt_error_return(regs, ESRCH);
-			goto out_tsk;
-		}
-	}
-	if (child->p_pptr != current) {
-		pt_error_return(regs, ESRCH);
+
+	ret = ptrace_check_attach(child, request == PTRACE_KILL);
+	if (ret < 0) {
+		pt_error_return(regs, -ret);
 		goto out_tsk;
 	}
 
diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
index 3500113..0b8fdbc 100644
--- a/arch/sparc64/kernel/signal.c
+++ b/arch/sparc64/kernel/signal.c
@@ -729,8 +729,8 @@
 				info.si_signo = signr;
 				info.si_errno = 0;
 				info.si_code = SI_USER;
-				info.si_pid = current->p_pptr->pid;
-				info.si_uid = current->p_pptr->uid;
+				info.si_pid = current->parent->pid;
+				info.si_uid = current->parent->uid;
 			}
 
 			/* If the (new) signal is now blocked, requeue it.  */
@@ -772,7 +772,7 @@
 				struct signal_struct *sig;
 
 				current->exit_code = signr;
-				sig = current->p_pptr->sig;
+				sig = current->parent->sig;
 				preempt_disable();
 				current->state = TASK_STOPPED;
 				if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags &
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
index e983d8f..a1985ce 100644
--- a/arch/sparc64/kernel/signal32.c
+++ b/arch/sparc64/kernel/signal32.c
@@ -1403,8 +1403,8 @@
 				info.si_signo = signr;
 				info.si_errno = 0;
 				info.si_code = SI_USER;
-				info.si_pid = current->p_pptr->pid;
-				info.si_uid = current->p_pptr->uid;
+				info.si_pid = current->parent->pid;
+				info.si_uid = current->parent->uid;
 			}
 
 			/* If the (new) signal is now blocked, requeue it.  */
@@ -1446,7 +1446,7 @@
 				struct signal_struct *sig;
 
 				current->exit_code = signr;
-				sig = current->p_pptr->sig;
+				sig = current->parent->sig;
 				preempt_disable();
 				current->state = TASK_STOPPED;
 				if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags &
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 24d26db..65389be 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -46,8 +46,8 @@
 volatile int __cpu_logical_map[NR_CPUS] __attribute__ ((aligned (SMP_CACHE_BYTES)));
 
 /* Please don't make this stuff initdata!!!  --DaveM */
-static unsigned char boot_cpu_id = 0;
-static int smp_activated = 0;
+static unsigned char boot_cpu_id;
+static int smp_activated;
 
 /* Kernel spinlock */
 spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
@@ -898,7 +898,7 @@
 
 static atomic_t smp_capture_depth = ATOMIC_INIT(0);
 static atomic_t smp_capture_registry = ATOMIC_INIT(0);
-static unsigned long penguins_are_doing_time = 0;
+static unsigned long penguins_are_doing_time;
 
 void smp_capture(void)
 {
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 250a4e2..8c675be 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -303,7 +303,6 @@
 EXPORT_SYMBOL(strchr);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strpbrk);
-EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strstr);
 
 #ifdef CONFIG_SOLARIS_EMUL_MODULE
diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
index 9fb202a..0c2eef4 100644
--- a/arch/sparc64/kernel/sys_sparc.c
+++ b/arch/sparc64/kernel/sys_sparc.c
@@ -380,7 +380,7 @@
 asmlinkage unsigned long
 c_sys_nis_syscall (struct pt_regs *regs)
 {
-	static int count=0;
+	static int count;
 	
 	/* Don't make the system unusable, if someone goes stuck */
 	if (count++ > 5)
@@ -450,7 +450,7 @@
 
 asmlinkage int solaris_syscall(struct pt_regs *regs)
 {
-	static int count = 0;
+	static int count;
 
 	regs->tpc = regs->tnpc;
 	regs->tnpc += 4;
@@ -470,7 +470,7 @@
 #ifndef CONFIG_SUNOS_EMUL
 asmlinkage int sunos_syscall(struct pt_regs *regs)
 {
-	static int count = 0;
+	static int count;
 
 	regs->tpc = regs->tnpc;
 	regs->tnpc += 4;
diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
index ae069fe..ab8c761 100644
--- a/arch/sparc64/kernel/sys_sunos32.c
+++ b/arch/sparc64/kernel/sys_sunos32.c
@@ -210,7 +210,7 @@
 
 asmlinkage void sunos_vadvise(u32 strategy)
 {
-	static int count = 0;
+	static int count;
 
 	/* I wanna see who uses this... */
 	if (count++ < 5)
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 88879f8..852c96d 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -62,7 +62,7 @@
 static __inline__ void timer_check_rtc(void)
 {
 	/* last time the cmos clock got updated */
-	static long last_rtc_update=0;
+	static long last_rtc_update;
 
 	/* Determine when to update the Mostek clock. */
 	if ((time_status & STA_UNSYNC) == 0 &&
@@ -410,7 +410,7 @@
 	struct linux_ebus *ebus = NULL;
 	struct isa_bridge *isa_br = NULL;
 #endif
-	static int invoked = 0;
+	static int invoked;
 
 	if (invoked)
 		return;
diff --git a/arch/sparc64/kernel/trampoline.S b/arch/sparc64/kernel/trampoline.S
index acd6d0a..5c90fbe3 100644
--- a/arch/sparc64/kernel/trampoline.S
+++ b/arch/sparc64/kernel/trampoline.S
@@ -215,13 +215,6 @@
 #define KERN_HIGHBITS		((_PAGE_VALID|_PAGE_SZ4MB)^0xfffff80000000000)
 #define KERN_LOWBITS		(_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
 
-#define VPTE_BASE_SPITFIRE	0xfffffffe00000000
-#if 1
-#define VPTE_BASE_CHEETAH	VPTE_BASE_SPITFIRE
-#else
-#define VPTE_BASE_CHEETAH	0xffe0000000000000
-#endif
-
 	mov		TSB_REG, %g1
 	stxa		%g0, [%g1] ASI_DMMU
 	membar		#Sync
@@ -252,8 +245,6 @@
 	clr	%g7
 #undef KERN_HIGHBITS
 #undef KERN_LOWBITS
-#undef VPTE_BASE_SPITFIRE
-#undef VPTE_BASE_CHEETAH
 
 	wrpr		%o1, 0x0, %pstate
 	ldx		[%g6 + TI_TASK], %g4
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 0534507..65ebe70 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -699,7 +699,7 @@
 	}
 }
 
-static int prom_ditlb_set = 0;
+static int prom_ditlb_set;
 struct prom_tlb_entry {
 	int		tlb_ent;
 	unsigned long	tlb_tag;
diff --git a/arch/sparc64/prom/bootstr.c b/arch/sparc64/prom/bootstr.c
index 064ba24..d5fa8f1 100644
--- a/arch/sparc64/prom/bootstr.c
+++ b/arch/sparc64/prom/bootstr.c
@@ -9,6 +9,11 @@
 #include <linux/init.h>
 #include <asm/oplib.h>
 
+/* WARNING: The boot loader knows that these next three variables come one right
+ *          after another in the .data section.  Do not move this stuff into
+ *          the .bss section or it will break things.
+ */
+
 #define BARG_LEN  256
 int bootstr_len = BARG_LEN;
 static int bootstr_valid = 0;
diff --git a/arch/sparc64/prom/misc.c b/arch/sparc64/prom/misc.c
index bb254f7..6f84b64 100644
--- a/arch/sparc64/prom/misc.c
+++ b/arch/sparc64/prom/misc.c
@@ -171,7 +171,7 @@
 
 static int prom_get_memory_ihandle(void)
 {
-	static int memory_ihandle_cache = 0;
+	static int memory_ihandle_cache;
 	int node, ret;
 
 	if (memory_ihandle_cache != 0)
diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
index 9831464..3a12280 100644
--- a/arch/sparc64/solaris/misc.c
+++ b/arch/sparc64/solaris/misc.c
@@ -57,7 +57,7 @@
 	/* Do we need it here? */
 	set_personality(PER_SVR4);
 	if (flags & MAP_NORESERVE) {
-		static int cnt = 0;
+		static int cnt;
 		
 		if (cnt < 5) {
 			printk("%s:  unimplemented Solaris MAP_NORESERVE mmap() flag\n",
diff --git a/arch/sparc64/solaris/timod.c b/arch/sparc64/solaris/timod.c
index 59e633f..8d3b591 100644
--- a/arch/sparc64/solaris/timod.c
+++ b/arch/sparc64/solaris/timod.c
@@ -46,7 +46,7 @@
 void * mykmalloc(size_t s, int gfp)
 {
 	static char * page;
-	static size_t free = 0;
+	static size_t free;
 	void * r;
 	s = ((s + 63) & ~63);
 	if( s > PAGE_SIZE ) {
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
index 0845e88..a38f476 100644
--- a/arch/x86_64/kernel/x8664_ksyms.c
+++ b/arch/x86_64/kernel/x8664_ksyms.c
@@ -87,7 +87,6 @@
 EXPORT_SYMBOL_NOVERS(__put_user_2);
 EXPORT_SYMBOL_NOVERS(__put_user_4);
 
-EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strstr);
 
diff --git a/drivers/acpi/acpi_tables.c b/drivers/acpi/acpi_tables.c
index 490e488..403fa5c 100644
--- a/drivers/acpi/acpi_tables.c
+++ b/drivers/acpi/acpi_tables.c
@@ -32,6 +32,7 @@
 #include <linux/types.h>
 #include <linux/irq.h>
 #include <linux/acpi.h>
+#include <linux/err.h>
 
 #define PREFIX			"ACPI: "
 
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index 638e8d0..9f14ddc 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -14,7 +14,6 @@
 #include <linux/sonet.h>
 #include <linux/skbuff.h>
 #include <linux/time.h>
-#include <linux/sched.h> /* for xtime */
 #include <linux/delay.h>
 #include <linux/uio.h>
 #include <linux/init.h>
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index d205bf2c..13fb4c7 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -5295,7 +5295,7 @@
       DAC960_ComputeGenericDiskInfo(Controller);
       DAC960_RegisterDisk(Controller, LogicalDriveNumber);
     }
-  if (Controller->GenericDiskInfo.sizes[MINOR(Inode->i_rdev)] == 0)
+  if (Controller->GenericDiskInfo.sizes[minor(Inode->i_rdev)] == 0)
     return -ENXIO;
   /*
     Increment Controller and Logical Drive Usage Counts.
@@ -6902,3 +6902,5 @@
 
 module_init(DAC960_Initialize);
 module_exit(DAC960_Finalize);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/block/blkpg.c b/drivers/block/blkpg.c
index 264d982..4992aa3 100644
--- a/drivers/block/blkpg.c
+++ b/drivers/block/blkpg.c
@@ -247,8 +247,8 @@
 		case BLKFLSBUF:
 			if (!capable(CAP_SYS_ADMIN))
 				return -EACCES;
-			fsync_dev(dev);
-			invalidate_buffers(dev);
+			fsync_bdev(bdev);
+			invalidate_bdev(bdev, 0);
 			return 0;
 
 		case BLKSSZGET:
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index d87635d..9e747ec 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -42,6 +42,7 @@
 #include <linux/blk.h>
 #include <linux/blkdev.h>
 #include <linux/genhd.h>
+#include <linux/completion.h>
 
 #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
 #define DRIVER_NAME "Compaq CISS Driver (v 2.5.0)"
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 5adb549..ceedd2d 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -32,6 +32,7 @@
 #include "../scsi/hosts.h" 
 #include <asm/atomic.h>
 #include <linux/timer.h>
+#include <linux/completion.h>
 
 #include "cciss_scsi.h"
 
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index bf0cec7..e02323f 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -22,6 +22,7 @@
 #include <linux/blk.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
+#include <linux/seq_file.h>
 
 
 static rwlock_t gendisk_lock;
@@ -142,39 +143,58 @@
 }
 
 #ifdef CONFIG_PROC_FS
-int
-get_partition_list(char *page, char **start, off_t offset, int count)
+/* iterator */
+static void *part_start(struct seq_file *part, loff_t *pos)
 {
-	struct gendisk *gp;
-	char buf[64];
-	int len, n;
+	loff_t k = *pos;
+	struct gendisk *sgp;
 
-	len = sprintf(page, "major minor  #blocks  name\n\n");
 	read_lock(&gendisk_lock);
-	for (gp = gendisk_head; gp; gp = gp->next) {
-		for (n = 0; n < (gp->nr_real << gp->minor_shift); n++) {
-			if (gp->part[n].nr_sects == 0)
-				continue;
+	for (sgp = gendisk_head; sgp; sgp = sgp->next) {
+		if (!k--)
+			return sgp;
+	}
+	return NULL;
+}
 
-			len += snprintf(page + len, 63,
-					"%4d  %4d %10d %s\n",
-					gp->major, n, gp->sizes[n],
-					disk_name(gp, n, buf));
-			if (len < offset)
-				offset -= len, len = 0;
-			else if (len >= offset + count)
-				goto out;
-		}
+static void *part_next(struct seq_file *part, void *v, loff_t *pos)
+{
+	++*pos;
+	return ((struct gendisk *)v)->next;
+}
+
+static void part_stop(struct seq_file *part, void *v)
+{
+	read_unlock(&gendisk_lock);
+}
+
+static int show_partition(struct seq_file *part, void *v)
+{
+	struct gendisk *sgp = v;
+	int n;
+	char buf[64];
+
+	if (sgp == gendisk_head)
+		seq_puts(part, "major minor  #blocks  name\n\n");
+
+	/* show all non-0 size partitions of this disk */
+	for (n = 0; n < (sgp->nr_real << sgp->minor_shift); n++) {
+		if (sgp->part[n].nr_sects == 0)
+			continue;
+		seq_printf(part, "%4d  %4d %10d %s\n",
+			sgp->major, n, sgp->sizes[n],
+			disk_name(sgp, n, buf));
 	}
 
-out:
-	read_unlock(&gendisk_lock);
-	*start = page + offset;
-	len -= offset;
-	if (len < 0)
-		len = 0;
-	return len > count ? count : len;
+	return 0;
 }
+
+struct seq_operations partitions_op = {
+	start:	part_start,
+	next:	part_next,
+	stop:	part_stop,
+	show:	show_partition
+};
 #endif
 
 
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index cfce7b2..cabf25e 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -36,6 +36,9 @@
  * Al Viro too.
  * Jens Axboe <axboe@suse.de>, Nov 2000
  *
+ * Support up to 256 loop devices
+ * Heinz Mauelshagen <mge@sistina.com>, Feb 2002
+ *
  * Still To Fix:
  * - Advisory locking is ignored here. 
  * - Should use an own CAP_* category instead of CAP_SYS_ADMIN 
@@ -927,7 +930,7 @@
  * And now the modules code and kernel interface.
  */
 MODULE_PARM(max_loop, "i");
-MODULE_PARM_DESC(max_loop, "Maximum number of loop devices (1-255)");
+MODULE_PARM_DESC(max_loop, "Maximum number of loop devices (1-256)");
 MODULE_LICENSE("GPL");
 
 int loop_register_transfer(struct loop_func_table *funcs)
@@ -963,9 +966,9 @@
 {
 	int	i;
 
-	if ((max_loop < 1) || (max_loop > 255)) {
+	if ((max_loop < 1) || (max_loop > 256)) {
 		printk(KERN_WARNING "loop: invalid max_loop (must be between"
-				    " 1 and 255), using default (8)\n");
+				    " 1 and 256), using default (8)\n");
 		max_loop = 8;
 	}
 
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index b13f0a8..ff6805f 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -327,7 +327,7 @@
 		req = CURRENT;
 #ifdef PARANOIA
 		if (!req)
-			FAIL("que not empty but no request?");
+			FAIL("queue not empty but no request?");
 #endif
 		dev = minor(req->rq_dev);
 #ifdef PARANOIA
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index f9cf01e..543ead8 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -405,9 +405,10 @@
 	for (i = 0 ; i < NUM_RAMDISKS; i++) {
 		struct block_device *bdev = rd_bdev[i];
 		rd_bdev[i] = NULL;
-		if (bdev)
+		if (bdev) {
+			invalidate_bdev(bdev, 1);
 			blkdev_put(bdev, BDEV_FILE);
-		destroy_buffers(mk_kdev(MAJOR_NR, i));
+		}
 	}
 
 	devfs_unregister (devfs_handle);
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 14107f2..fc2fa88 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -1107,6 +1107,7 @@
 
 	/* Misc */
 	case DVD_INVALIDATE_AGID:
+		cgc.quiet = 1;
 		cdinfo(CD_DVD, "entering DVD_INVALIDATE_AGID\n"); 
 		setup_report_key(&cgc, ai->lsa.agid, 0x3f);
 		if ((ret = cdo->generic_packet(cdi, &cgc)))
diff --git a/drivers/char/acquirewdt.c b/drivers/char/acquirewdt.c
index 37a3420..a7ea695 100644
--- a/drivers/char/acquirewdt.c
+++ b/drivers/char/acquirewdt.c
@@ -17,6 +17,9 @@
  *
  *	(c) Copyright 1995    Alan Cox <alan@redhat.com>
  *
+ *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *          Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *          Can't add timeout - driver doesn't allow changing value
  */
 
 #include <linux/config.h>
@@ -50,8 +53,14 @@
 #define WDT_STOP 0x43
 #define WDT_START 0x443
 
-#define WD_TIMO (100*60)		/* 1 minute */
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
 
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
 
 /*
  *	Kernel methods.
@@ -126,10 +135,13 @@
 				spin_unlock(&acq_lock);
 				return -EBUSY;
 			}
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			/*
 			 *	Activate 
 			 */
-	 
+
 			acq_is_open=1;
 			inb_p(WDT_START);      
 			spin_unlock(&acq_lock);
@@ -144,9 +156,9 @@
 	if(minor(inode->i_rdev)==WATCHDOG_MINOR)
 	{
 		spin_lock(&acq_lock);
-#ifndef CONFIG_WATCHDOG_NOWAYOUT	
-		inb_p(WDT_STOP);
-#endif		
+		if (!nowayout) {
+			inb_p(WDT_STOP);
+		}
 		acq_is_open=0;
 		spin_unlock(&acq_lock);
 	}
diff --git a/drivers/char/advantechwdt.c b/drivers/char/advantechwdt.c
index b40df81..3e6940f 100644
--- a/drivers/char/advantechwdt.c
+++ b/drivers/char/advantechwdt.c
@@ -20,6 +20,9 @@
  *
  *	(c) Copyright 1995    Alan Cox <alan@redhat.com>
  *
+ *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *          Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *          Added timeout module option to override default
  */
 
 #include <linux/config.h>
@@ -56,8 +59,7 @@
  *	the manual says WDT_STOP is 0x43, not 0x443).
  *	(0x43 is also a write-only control register for the 8254 timer!)
  *
- *	TODO: module parameters to set the I/O port addresses and NOWAYOUT
- *	option at load time.
+ *	TODO: module parameters to set the I/O port addresses
  */
  
 #define WDT_STOP 0x443
@@ -65,6 +67,19 @@
 
 #define WD_TIMO 60		/* 1 minute */
 
+static int timeout = WD_TIMO;	/* in seconds */
+MODULE_PARM(timeout,"i");
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)"); 
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
 /*
  *	Kernel methods.
  */
@@ -73,7 +88,7 @@
 advwdt_ping(void)
 {
 	/* Write a watchdog value */
-	outb_p(WD_TIMO, WDT_START);
+	outb_p(timeout, WDT_START);
 }
 
 static ssize_t
@@ -135,6 +150,9 @@
 				spin_unlock(&advwdt_lock);
 				return -EBUSY;
 			}
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			/*
 			 *	Activate 
 			 */
@@ -153,9 +171,9 @@
 {
 	if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
 		spin_lock(&advwdt_lock);
-#ifndef CONFIG_WATCHDOG_NOWAYOUT	
-		inb_p(WDT_STOP);
-#endif		
+		if (!nowayout) {
+			inb_p(WDT_STOP);
+		}
 		advwdt_is_open = 0;
 		spin_unlock(&advwdt_lock);
 	}
@@ -207,11 +225,21 @@
 	0
 };
 
+static void __init
+advwdt_validate_timeout(void)
+{
+	if (timeout < 1 || timeout > 63) {
+		timeout = WD_TIMO;
+		printk(KERN_INFO "advantechwdt: timeout value must be 1 <= x <= 63, using %d\n", timeout);
+	}
+}
+
 static int __init
 advwdt_init(void)
 {
 	printk("WDT driver for Advantech single board computer initialising.\n");
 
+	advwdt_validate_timeout();
 	spin_lock_init(&advwdt_lock);
 	misc_register(&advwdt_miscdev);
 #if WDT_START != WDT_STOP
diff --git a/drivers/char/agp/agpgart_be.c b/drivers/char/agp/agpgart_be.c
index fdd404f..de7f2ed 100644
--- a/drivers/char/agp/agpgart_be.c
+++ b/drivers/char/agp/agpgart_be.c
@@ -397,7 +397,7 @@
 static void agp_generic_agp_enable(u32 mode)
 {
 	struct pci_dev *device = NULL;
-	u32 command, scratch, cap_id;
+	u32 command, scratch; 
 	u8 cap_ptr;
 
 	pci_read_config_dword(agp_bridge.dev,
@@ -410,34 +410,8 @@
 	 */
 
 
-	pci_for_each_dev(device)
-	{
-		/*
-		 *	Enable AGP devices. Most will be VGA display but
-		 *	some may be coprocessors on non VGA devices too
-		 */
-		 
-		if((((device->class >> 16) & 0xFF) != PCI_BASE_CLASS_DISPLAY) &&
-			(device->class != (PCI_CLASS_PROCESSOR_CO << 8)))
-			continue;
-
-		pci_read_config_dword(device, 0x04, &scratch);
-
-		if (!(scratch & 0x00100000))
-			continue;
-
-		pci_read_config_byte(device, 0x34, &cap_ptr);
-
-		if (cap_ptr != 0x00) {
-			do {
-				pci_read_config_dword(device,
-						      cap_ptr, &cap_id);
-
-				if ((cap_id & 0xff) != 0x02)
-					cap_ptr = (cap_id >> 8) & 0xff;
-			}
-			while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00));
-		}
+	pci_for_each_dev(device) {
+		cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP);
 		if (cap_ptr != 0x00) {
 			/*
 			 * Ok, here we have a AGP device. Disable impossible 
@@ -506,25 +480,8 @@
 	 *        command registers.
 	 */
 
-	while ((device = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8,
-					device)) != NULL) {
-		pci_read_config_dword(device, 0x04, &scratch);
-
-		if (!(scratch & 0x00100000))
-			continue;
-
-		pci_read_config_byte(device, 0x34, &cap_ptr);
-
-		if (cap_ptr != 0x00) {
-			do {
-				pci_read_config_dword(device,
-						      cap_ptr, &cap_id);
-
-				if ((cap_id & 0xff) != 0x02)
-					cap_ptr = (cap_id >> 8) & 0xff;
-			}
-			while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00));
-		}
+	pci_for_each_dev(device) {
+		cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP);
 		if (cap_ptr != 0x00)
 			pci_write_config_dword(device, cap_ptr + 8, command);
 	}
@@ -809,9 +766,9 @@
 	struct page * page;
 	
 	page = alloc_page(GFP_KERNEL);
-	if (page == NULL) {
+	if (page == NULL)
 		return 0;
-	}
+
 	get_page(page);
 	LockPage(page);
 	atomic_inc(&agp_bridge.current_memory_agp);
@@ -823,10 +780,9 @@
 	void *pt = (void *) addr;
 	struct page *page;
 
-	if (pt == NULL) {
+	if (pt == NULL)
 		return;
-	}
-	
+
 	page = virt_to_page(pt);
 	put_page(page);
 	UnlockPage(page);
@@ -3318,24 +3274,8 @@
 	 */
 
 
-	pci_for_each_dev(device)
-	{
-		/*
-		 *	Enable AGP devices. Most will be VGA display but
-		 *	some may be coprocessors on non VGA devices too
-		 */
-		 
-		if((((device->class >> 16) & 0xFF) != PCI_BASE_CLASS_DISPLAY) &&
-			(device->class != (PCI_CLASS_PROCESSOR_CO << 8)))
-			continue;
-
-		pci_read_config_dword(device, 0x04, &scratch);
-
-		if (!(scratch & 0x00100000))
-			continue;
-
-		pci_read_config_byte(device, 0x34, &cap_ptr);
-
+	pci_for_each_dev(device) {
+		cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP);
 		if (cap_ptr != 0x00) {
 			do {
 				pci_read_config_dword(device,
@@ -3413,25 +3353,8 @@
 	 *        command registers.
 	 */
 
-	while ((device = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8,
-					device)) != NULL) {
-		pci_read_config_dword(device, 0x04, &scratch);
-
-		if (!(scratch & 0x00100000))
-			continue;
-
-		pci_read_config_byte(device, 0x34, &cap_ptr);
-
-		if (cap_ptr != 0x00) {
-			do {
-				pci_read_config_dword(device,
-						      cap_ptr, &cap_id);
-
-				if ((cap_id & 0xff) != 0x02)
-					cap_ptr = (cap_id >> 8) & 0xff;
-			}
-			while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00));
-		}
+	pci_for_each_dev(device) {
+		cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP);
 		if (cap_ptr != 0x00)
 			pci_write_config_dword(device, cap_ptr + 8, command);
 	}
@@ -3881,7 +3804,6 @@
 {
 	struct pci_dev *dev = NULL;
 	u8 cap_ptr = 0x00;
-	u32 cap_id, scratch;
 
 	if ((dev = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8, NULL)) == NULL)
 		return -ENODEV;
@@ -4022,20 +3944,7 @@
 #endif	/* CONFIG_AGP_SWORKS */
 
 	/* find capndx */
-	pci_read_config_dword(dev, 0x04, &scratch);
-	if (!(scratch & 0x00100000))
-		return -ENODEV;
-
-	pci_read_config_byte(dev, 0x34, &cap_ptr);
-	if (cap_ptr != 0x00) {
-		do {
-			pci_read_config_dword(dev, cap_ptr, &cap_id);
-
-			if ((cap_id & 0xff) != 0x02)
-				cap_ptr = (cap_id >> 8) & 0xff;
-		}
-		while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00));
-	}
+	cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP);
 	if (cap_ptr == 0x00)
 		return -ENODEV;
 	agp_bridge.capndx = cap_ptr;
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index fe21688..9db606a 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -36,7 +36,7 @@
 
 #if LINUX_VERSION_CODE < 0x20300 
 /* These probably want adding to <linux/compatmac.h> */
-#define init_waitqueue_head(x) do { *(x) = NULL; } while (0);
+#define init_waitqueue_head(x) do { *(x) = NULL; } while (0)
 #define PCI_BASE_ADDRESS(dev) (dev->base_address[0])
 #define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue *x
 #define __setup(x,y) /* */
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 47f9736..0d7a56a 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -4965,6 +4965,8 @@
   uclong		Ze_addr0[NR_CARDS], Ze_addr2[NR_CARDS], ZeIndex = 0;
   uclong		Ze_phys0[NR_CARDS], Ze_phys2[NR_CARDS];
   unsigned char         Ze_irq[NR_CARDS];
+  struct resource *resource;
+  unsigned long res_start, res_len;
 
         for (i = 0; i < NR_CARDS; i++) {
                 /* look for a Cyclades card by vendor and device id */
@@ -5012,7 +5014,15 @@
 		/* Although we don't use this I/O region, we should
 		   request it from the kernel anyway, to avoid problems
 		   with other drivers accessing it. */
-		request_region(cy_pci_phys1, CyPCI_Yctl, "Cyclom-Y");
+		resource = request_region(cy_pci_phys1,
+					CyPCI_Yctl, "Cyclom-Y");
+		if (resource == NULL) {
+			printk(KERN_ERR "cyclades: failed to allocate IO "
+					"resource at 0x%lx\n", cy_pci_phys1);
+			continue;
+		}
+		res_start = cy_pci_phys1;
+		res_len = CyPCI_Yctl;
 
 #if defined(__alpha__)
                 if (device_id  == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */
@@ -5083,7 +5093,11 @@
                 cy_card[j].bus_index = 1;
                 cy_card[j].first_line = cy_next_channel;
                 cy_card[j].num_chips = cy_pci_nchan/4;
-
+		cy_card[j].resource = resource;
+		cy_card[j].res_start = res_start;
+		cy_card[j].res_len = res_len;
+		resource = NULL;	/* For next card */
+	
                 /* enable interrupts in the PCI interface */
 		plx_ver = cy_readb(cy_pci_addr2 + CyPLX_VER) & 0x0f;
 		switch (plx_ver) {
@@ -5162,8 +5176,16 @@
 		/* Although we don't use this I/O region, we should
 		   request it from the kernel anyway, to avoid problems
 		   with other drivers accessing it. */
-		request_region(cy_pci_phys1, CyPCI_Zctl, "Cyclades-Z");
-
+		resource = request_region(cy_pci_phys1,
+				CyPCI_Zctl, "Cyclades-Z");
+		if (resource == NULL) {
+			printk(KERN_ERR "cyclades: failed ot allocate IO resource "
+					"at 0x%lx\n", cy_pci_phys1);
+			continue;
+		}
+		res_start = cy_pci_phys1;
+		res_len = CyPCI_Zctl;
+	
 		if (mailbox == ZE_V1) {
 		    cy_pci_addr2 = (ulong)ioremap(cy_pci_phys2, CyPCI_Ze_win);
 		    if (ZeIndex == NR_CARDS) {
@@ -5261,6 +5283,10 @@
                 cy_card[j].bus_index = 1;
                 cy_card[j].first_line = cy_next_channel;
                 cy_card[j].num_chips = -1;
+		cy_card[j].resource = resource;
+		cy_card[j].res_start = res_start;
+		cy_card[j].res_len = res_len;
+		resource = NULL;	/* For next card */
 
                 /* print message */
 #ifdef CONFIG_CYZ_INTR
@@ -5279,7 +5305,7 @@
                 printk("%d channels starting from port %d.\n",
 		    cy_pci_nchan,cy_next_channel);
                 cy_next_channel += cy_pci_nchan;
-    }
+	    }
         }
 
         for (; ZeIndex != 0 && i < NR_CARDS; i++) {
@@ -5787,6 +5813,8 @@
 #endif /* CONFIG_CYZ_INTR */
 	    )
 		free_irq(cy_card[i].irq, &cy_card[i]);
+		if (cy_card[i].resource)
+			release_region(cy_card[i].res_start, cy_card[i].res_len);
         }
     }
     if (tmp_buf) {
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index 8629e0e..86a9733 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -73,7 +73,7 @@
 	*(volatile unsigned int *)(virt + outring) = n;			\
 	outring += 4;							\
 	outring &= ringmask;						\
-} while (0);
+} while (0)
 
 static inline void i810_print_status_page(drm_device_t *dev)
 {
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 97f842c..c6a9c35 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -2161,7 +2161,7 @@
 		if (signal_pending(current))
 			break;
 
-		if (timeout && ((orig_jiffies + timeout) < jiffies))
+		if (timeout && time_after(jiffies, orig_jiffies + timeout))
 			break;
 
 		serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
diff --git a/drivers/char/eurotechwdt.c b/drivers/char/eurotechwdt.c
index 2907315..698a2e3 100644
--- a/drivers/char/eurotechwdt.c
+++ b/drivers/char/eurotechwdt.c
@@ -20,6 +20,10 @@
  *      "AS-IS" and at no charge.
  *
  *      (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>*
+ *
+ *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *          Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *          Added timeout module option to override default
  */
 
 #include <linux/config.h>
@@ -45,7 +49,6 @@
 #include <linux/smp_lock.h>
 
 static int eurwdt_is_open;
-static int eurwdt_timeout; 
 static spinlock_t eurwdt_lock;
  
 /*
@@ -58,6 +61,18 @@
 static char *ev = "int";
  
 #define WDT_TIMEOUT		60                /* 1 minute */
+static int timeout = WDT_TIMEOUT;
+
+MODULE_PARM(timeout,"i");
+MODULE_PARM_DESC(timeout, "Eurotech WDT timeout in seconds (default=60)"); 
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
 
 
 /*
@@ -116,6 +131,15 @@
  *      Programming support
  */
 
+static void __init eurwdt_validate_timeout(void)
+{
+	if (timeout < 0 || timeout > 255) {
+		timeout = WDT_TIMEOUT;
+		printk(KERN_INFO "eurwdt: timeout must be 0 < x < 255, using %d\n",
+		       timeout);
+	}
+}
+
 static inline void eurwdt_write_reg(u8 index, u8 data)
 {
    outb(index, io);
@@ -189,7 +213,7 @@
 static void eurwdt_ping(void)
 {
    /* Write the watchdog default value */
-   eurwdt_set_timeout(eurwdt_timeout);
+   eurwdt_set_timeout(timeout);
 }
  
 /**
@@ -263,7 +287,7 @@
          if (time < 0 || time > 255)
             return -EINVAL;
 
-         eurwdt_timeout = time; 
+         timeout = time; 
          eurwdt_set_timeout(time); 
          return 0;
    }
@@ -287,9 +311,11 @@
             spin_unlock(&eurwdt_lock);
             return -EBUSY;
          }
+	 if (nowayout) {
+		 MOD_INC_USE_COUNT;
+	 }
 
          eurwdt_is_open = 1;
-         eurwdt_timeout = WDT_TIMEOUT;   /* initial timeout */
 
          /* Activate the WDT */
          eurwdt_activate_timer(); 
@@ -323,12 +349,12 @@
 static int eurwdt_release(struct inode *inode, struct file *file)
 {
    if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-      eurwdt_disable_timer();
-#endif
-      eurwdt_is_open = 0;
+	   if (!nowayout) {
+		   eurwdt_disable_timer();
+	   }
+	   eurwdt_is_open = 0;
 
-      MOD_DEC_USE_COUNT;
+	   MOD_DEC_USE_COUNT;
    }
 
    return 0;
@@ -422,7 +448,8 @@
 static int __init eurwdt_init(void)
 {
    int ret;
- 
+
+   eurwdt_validate_timeout();
    ret = misc_register(&eurwdt_miscdev);
    if (ret) {
       printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n",
diff --git a/drivers/char/i810-tco.c b/drivers/char/i810-tco.c
index 90c8e48..5b20720 100644
--- a/drivers/char/i810-tco.c
+++ b/drivers/char/i810-tco.c
@@ -1,5 +1,5 @@
 /*
- *	i810-tco 0.02:	TCO timer driver for i810 chipsets
+ *	i810-tco 0.03:	TCO timer driver for i810 chipsets
  *
  *	(c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
  *				http://www.kernelconcepts.de
@@ -28,6 +28,9 @@
  *	Initial Version 0.01
  *  20000728 Nils Faerber
  *      0.02 Fix for SMI_EN->TCO_EN bit, some cleanups
+ *  20011214 Matt Domsch <Matt_Domsch@dell.com>
+ *      0.03 Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *           Didn't add timeout option as i810_margin already exists.
  */
  
 #include <linux/module.h>
@@ -60,6 +63,18 @@
 static int i810_margin = TIMER_MARGIN;	/* steps of 0.6sec */
 
 MODULE_PARM (i810_margin, "i");
+MODULE_PARM_DESC(i810_margin, "Watchdog timeout in steps of 0.6sec, 2<n<64. Default = 50 (30 seconds)");
+
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
 
 /*
  *	Timer active flag
@@ -167,6 +182,9 @@
 	if (timer_alive)
 		return -EBUSY;
 
+	if (nowayout) {
+		MOD_INC_USE_COUNT;
+	}
 	/*
 	 *      Reload and activate timer
 	 */
@@ -181,10 +199,10 @@
 	/*
 	 *      Shut off the timer.
 	 */
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
-	tco_timer_stop ();
-	timer_alive = 0;
-#endif	
+	if (nowayout) {
+		tco_timer_stop ();
+		timer_alive = 0;
+	}
 	return 0;
 }
 
@@ -342,8 +360,8 @@
 	tco_timer_reload ();
 
 	printk (KERN_INFO
-		"i810 TCO timer: V0.02, timer margin: %d sec (0x%04x)\n",
-		(int) (i810_margin * 6 / 10), TCOBASE);
+		"i810 TCO timer: V0.03, timer margin: %d sec (0x%04x), nowayout: %d\n",
+		(int) (i810_margin * 6 / 10), TCOBASE, nowayout);
 	return 0;
 }
 
diff --git a/drivers/char/ib700wdt.c b/drivers/char/ib700wdt.c
index 91fb96c..8f7c167 100644
--- a/drivers/char/ib700wdt.c
+++ b/drivers/char/ib700wdt.c
@@ -25,6 +25,10 @@
  *
  *	(c) Copyright 1995    Alan Cox <alan@redhat.com>
  *
+ *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *           Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *           Added timeout module option to override default
+ * 
  */
 
 #include <linux/config.h>
@@ -92,15 +96,36 @@
 
 #define WD_TIMO 0		/* 30 seconds +/- 20%, from table */
 
+static int timeout_val = WD_TIMO;	/* value in table */
+static int timeout = 30;	        /* in seconds */
+MODULE_PARM(timeout,"i");
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, 0 < n < 30, must be even (default=30)");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
 /*
  *	Kernel methods.
  */
 
+static void __init
+ibwdt_validate_timeout(void)
+{
+	timeout_val = (30 - timeout) / 2;
+	if (timeout_val < 0 || timeout_val > 0xF) timeout_val = WD_TIMO;
+}
+
 static void
 ibwdt_ping(void)
 {
 	/* Write a watchdog value */
-	outb_p(WD_TIMO, WDT_START);
+	outb_p(timeout_val, WDT_START);
 }
 
 static ssize_t
@@ -162,6 +187,9 @@
 				spin_unlock(&ibwdt_lock);
 				return -EBUSY;
 			}
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			/*
 			 *	Activate
 			 */
@@ -181,9 +209,9 @@
 	lock_kernel();
 	if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
 		spin_lock(&ibwdt_lock);
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-		outb_p(WD_TIMO, WDT_STOP);
-#endif
+		if (!nowayout) {
+			outb_p(timeout_val, WDT_STOP);
+		}
 		ibwdt_is_open = 0;
 		spin_unlock(&ibwdt_lock);
 	}
@@ -201,7 +229,7 @@
 {
 	if (code == SYS_DOWN || code == SYS_HALT) {
 		/* Turn the WDT off */
-		outb_p(WD_TIMO, WDT_STOP);
+		outb_p(timeout_val, WDT_STOP);
 	}
 	return NOTIFY_DONE;
 }
@@ -241,6 +269,7 @@
 {
 	printk("WDT driver for IB700 single board computer initialising.\n");
 
+	ibwdt_validate_timeout();
 	spin_lock_init(&ibwdt_lock);
 	misc_register(&ibwdt_miscdev);
 #if WDT_START != WDT_STOP
diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c
index 9572ee2..4955f59 100644
--- a/drivers/char/ip2/i2lib.c
+++ b/drivers/char/ip2/i2lib.c
@@ -1330,7 +1330,7 @@
 
 	// if expires == 0 then timer poped, then do not need to del_timer
 	if ((timeout > 0) && pCh->BookmarkTimer.expires && 
-				(pCh->BookmarkTimer.expires > jiffies)) {
+	                     time_before(jiffies, pCh->BookmarkTimer.expires)) {
 		del_timer( &(pCh->BookmarkTimer) );
 		pCh->BookmarkTimer.expires = 0;
 
diff --git a/drivers/char/machzwd.c b/drivers/char/machzwd.c
index 8765b67..85ba832 100644
--- a/drivers/char/machzwd.c
+++ b/drivers/char/machzwd.c
@@ -24,6 +24,8 @@
  *  a system RESET and it starts wd#2 that unconditionaly will RESET 
  *  the system when the counter reaches zero.
  *
+ *  14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *      Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
  */
 
 #include <linux/config.h>
@@ -103,6 +105,15 @@
 MODULE_PARM(action, "i");
 MODULE_PARM_DESC(action, "after watchdog resets, generate: 0 = RESET(*)  1 = SMI  2 = NMI  3 = SCI");
 
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
 #define PFX "machzwd"
 
 static struct watchdog_info zf_info = {
@@ -307,23 +318,23 @@
  * no need to check for close confirmation
  * no way to disable watchdog ;)
  */
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-		size_t ofs;
-
-		/* 
-		 * note: just in case someone wrote the magic character
-		 * five months ago...
-		 */
-		zf_expect_close = 0;
-
-		/* now scan */
-		for(ofs = 0; ofs != count; ofs++){
-			if(buf[ofs] == 'V'){
-				zf_expect_close = 1;
-				dprintk("zf_expect_close 1\n");
+		if (!nowayout) {
+			size_t ofs;
+			
+			/* 
+			 * note: just in case someone wrote the magic character
+			 * five months ago...
+			 */
+			zf_expect_close = 0;
+			
+			/* now scan */
+			for(ofs = 0; ofs != count; ofs++){
+				if(buf[ofs] == 'V'){
+					zf_expect_close = 1;
+					dprintk("zf_expect_close 1\n");
+				}
 			}
 		}
-#endif
 		/*
 		 * Well, anyhow someone wrote to us,
 		 * we should return that favour
@@ -386,9 +397,9 @@
 				return -EBUSY;
 			}
 
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
-			MOD_INC_USE_COUNT;
-#endif
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			zf_is_open = 1;
 
 			spin_unlock(&zf_lock);
diff --git a/drivers/char/mixcomwd.c b/drivers/char/mixcomwd.c
index 3f6e87a..bbcb881 100644
--- a/drivers/char/mixcomwd.c
+++ b/drivers/char/mixcomwd.c
@@ -27,10 +27,13 @@
  *
  * Version 0.4 (99/11/15):
  *		- support for one more type board
+ *
+ * Version 0.5 (2001/12/14) Matt Domsch <Matt_Domsch@dell.com>
+ *              - added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
  *	
  */
 
-#define VERSION "0.4" 
+#define VERSION "0.5" 
   
 #include <linux/module.h>
 #include <linux/config.h>
@@ -57,26 +60,30 @@
 static long mixcomwd_opened; /* long req'd for setbit --RR */
 
 static int watchdog_port;
-
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
 static int mixcomwd_timer_alive;
 static struct timer_list mixcomwd_timer;
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
 #endif
 
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
 static void mixcomwd_ping(void)
 {
 	outb_p(55,watchdog_port);
 	return;
 }
 
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
 static void mixcomwd_timerfun(unsigned long d)
 {
 	mixcomwd_ping();
 	
 	mod_timer(&mixcomwd_timer,jiffies+ 5*HZ);
 }
-#endif
 
 /*
  *	Allow only one person to hold it open
@@ -89,31 +96,32 @@
 	}
 	mixcomwd_ping();
 	
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-	if(mixcomwd_timer_alive) {
-		del_timer(&mixcomwd_timer);
-		mixcomwd_timer_alive=0;
-	} 
-#endif
+	if (nowayout) {
+		MOD_INC_USE_COUNT;
+	} else {
+		if(mixcomwd_timer_alive) {
+			del_timer(&mixcomwd_timer);
+			mixcomwd_timer_alive=0;
+		}
+	}
 	return 0;
 }
 
 static int mixcomwd_release(struct inode *inode, struct file *file)
 {
 
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-	if(mixcomwd_timer_alive) {
-		printk(KERN_ERR "mixcomwd: release called while internal timer alive");
-		return -EBUSY;
+	if (!nowayout) {
+		if(mixcomwd_timer_alive) {
+			printk(KERN_ERR "mixcomwd: release called while internal timer alive");
+			return -EBUSY;
+		}
+		init_timer(&mixcomwd_timer);
+		mixcomwd_timer.expires=jiffies + 5 * HZ;
+		mixcomwd_timer.function=mixcomwd_timerfun;
+		mixcomwd_timer.data=0;
+		mixcomwd_timer_alive=1;
+		add_timer(&mixcomwd_timer);
 	}
-	init_timer(&mixcomwd_timer);
-	mixcomwd_timer.expires=jiffies + 5 * HZ;
-	mixcomwd_timer.function=mixcomwd_timerfun;
-	mixcomwd_timer.data=0;
-	mixcomwd_timer_alive=1;
-	add_timer(&mixcomwd_timer);
-#endif
-
 	clear_bit(0,&mixcomwd_opened);
 	return 0;
 }
@@ -145,9 +153,9 @@
 	{
 		case WDIOC_GETSTATUS:
 			status=mixcomwd_opened;
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-			status|=mixcomwd_timer_alive;
-#endif
+			if (!nowayout) {
+				status|=mixcomwd_timer_alive;
+			}
 			if (copy_to_user((int *)arg, &status, sizeof(int))) {
 				return -EFAULT;
 			}
@@ -252,14 +260,14 @@
 
 static void __exit mixcomwd_exit(void)
 {
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-	if(mixcomwd_timer_alive) {
-		printk(KERN_WARNING "mixcomwd: I quit now, hardware will"
-			" probably reboot!\n");
-		del_timer(&mixcomwd_timer);
-		mixcomwd_timer_alive=0;
+	if (!nowayout) {
+		if(mixcomwd_timer_alive) {
+			printk(KERN_WARNING "mixcomwd: I quit now, hardware will"
+			       " probably reboot!\n");
+			del_timer(&mixcomwd_timer);
+			mixcomwd_timer_alive=0;
+		}
 	}
-#endif
 	release_region(watchdog_port,1);
 	misc_deregister(&mixcomwd_miscdev);
 }
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 12a0fd3..6d0512e 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -32,6 +32,9 @@
  *      version         : 1.2 
  *      
  *    Fixes for C104H/PCI by Tim Hockin <thockin@sun.com>
+ *    Added support for: C102, CI-132, CI-134, CP-132, CP-114, CT-114 cards
+ *                        by Damian Wrobel <dwrobel@ertel.com.pl>
+ *
  */
 
 #include <linux/config.h>
@@ -61,7 +64,7 @@
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
 
-#define		MXSER_VERSION			"1.2"
+#define		MXSER_VERSION			"1.2.1"
 
 #define		MXSERMAJOR	 	174
 #define		MXSERCUMAJOR		175
@@ -114,10 +117,22 @@
 #ifndef PCI_DEVICE_ID_C104
 #define PCI_DEVICE_ID_C104	0x1040
 #endif
+#ifndef PCI_DEVICE_ID_CP132
+#define PCI_DEVICE_ID_CP132	0x1320
+#endif
+#ifndef PCI_DEVICE_ID_CP114
+#define PCI_DEVICE_ID_CP114	0x1141
+#endif
+#ifndef PCI_DEVICE_ID_CT114
+#define PCI_DEVICE_ID_CT114	0x1140
+#endif
 
 #define C168_ASIC_ID    1
 #define C104_ASIC_ID    2
+#define CI134_ASIC_ID   3
+#define CI132_ASIC_ID   4
 #define CI104J_ASIC_ID  5
+#define C102_ASIC_ID	0xB
 
 enum {
 	MXSER_BOARD_C168_ISA = 0,
@@ -125,6 +140,12 @@
 	MXSER_BOARD_CI104J,
 	MXSER_BOARD_C168_PCI,
 	MXSER_BOARD_C104_PCI,
+	MXSER_BOARD_C102_ISA,
+	MXSER_BOARD_CI132,
+	MXSER_BOARD_CI134,
+	MXSER_BOARD_CP132_PCI,
+	MXSER_BOARD_CP114_PCI,
+	MXSER_BOARD_CT114_PCI
 };
 
 static char *mxser_brdname[] =
@@ -134,6 +155,12 @@
 	"CI-104J series",
 	"C168H/PCI series",
 	"C104H/PCI series",
+	"C102 series",
+	"CI-132 series",
+	"CI-134 series",
+	"CP-132 series",
+	"CP-114 series",
+	"CT-114 series"
 };
 
 static int mxser_numports[] =
@@ -143,6 +170,12 @@
 	4,
 	8,
 	4,
+	2,
+	2,
+	4,
+	2,
+	4,
+	4
 };
 
 /*
@@ -163,6 +196,12 @@
 	  MXSER_BOARD_C168_PCI },
 	{ PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
 	  MXSER_BOARD_C104_PCI },
+	{ PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CP132, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  MXSER_BOARD_CP132_PCI },
+	{ PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CP114, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  MXSER_BOARD_CP114_PCI },
+	{ PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CT114, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  MXSER_BOARD_CT114_PCI },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, mxser_pcibrds);
@@ -613,38 +652,35 @@
 		n = (sizeof(mxser_pcibrds) / sizeof(mxser_pcibrds[0])) - 1;
 		index = 0;
 		for (b = 0; b < n; b++) {
-			pdev = pci_find_device(mxser_pcibrds[b].vendor,
-					       mxser_pcibrds[b].device, pdev);
-			if (!pdev || pci_enable_device(pdev))
-				continue;
-			hwconf.pdev = pdev;
-			printk("Found MOXA %s board(BusNo=%d,DevNo=%d)\n",
-				mxser_brdname[mxser_pcibrds[b].driver_data],
+			while (pdev = pci_find_device(mxser_pcibrds[b].vendor, mxser_pcibrds[b].device, pdev)) 
+			{
+				if (pci_enable_device(pdev))
+					continue;
+				hwconf.pdev = pdev;
+				printk("Found MOXA %s board(BusNo=%d,DevNo=%d)\n",
+					mxser_brdname[mxser_pcibrds[b].driver_data],
 				pdev->bus->number, PCI_SLOT(pdev->devfn));
-			if (m >= MXSER_BOARDS) {
-				printk("Too many Smartio family boards found (maximum %d),board not configured\n", MXSER_BOARDS);
-			} else {
-				retval = mxser_get_PCI_conf(pdev,
-				   mxser_pcibrds[b].driver_data, &hwconf);
-				if (retval < 0) {
-					if (retval == MXSER_ERR_IRQ)
-						printk("Invalid interrupt number,board not configured\n");
-					else if (retval == MXSER_ERR_IRQ_CONFLIT)
-						printk("Invalid interrupt number,board not configured\n");
-					else if (retval == MXSER_ERR_VECTOR)
-						printk("Invalid interrupt vector,board not configured\n");
-					else if (retval == MXSER_ERR_IOADDR)
-						printk("Invalid I/O address,board not configured\n");
-					continue;
-
+				if (m >= MXSER_BOARDS) {
+					printk("Too many Smartio family boards found (maximum %d),board not configured\n", MXSER_BOARDS);
+				} else {
+					retval = mxser_get_PCI_conf(pdev, mxser_pcibrds[b].driver_data, &hwconf);
+					if (retval < 0) {
+						if (retval == MXSER_ERR_IRQ)
+							printk("Invalid interrupt number,board not configured\n");
+						else if (retval == MXSER_ERR_IRQ_CONFLIT)
+							printk("Invalid interrupt number,board not configured\n");	
+						else if (retval == MXSER_ERR_VECTOR)
+							printk("Invalid interrupt vector,board not configured\n");
+						else if (retval == MXSER_ERR_IOADDR)
+							printk("Invalid I/O address,board not configured\n");
+						continue;
+					}
+					if (mxser_initbrd(m, &hwconf) < 0)
+						continue;
+					mxser_getcfg(m, &hwconf);
+					m++;
 				}
-				if (mxser_initbrd(m, &hwconf) < 0)
-					continue;
-				mxser_getcfg(m, &hwconf);
-				m++;
-
 			}
-
 		}
 	}
 #endif
@@ -2306,6 +2342,12 @@
 		hwconf->board_type = MXSER_BOARD_C168_ISA;
 	else if (id == C104_ASIC_ID)
 		hwconf->board_type = MXSER_BOARD_C104_ISA;
+	else if (id == C102_ASIC_ID)
+		hwconf->board_type = MXSER_BOARD_C102_ISA;
+	else if (id == CI132_ASIC_ID)
+		hwconf->board_type = MXSER_BOARD_CI132;
+	else if (id == CI134_ASIC_ID)
+		hwconf->board_type = MXSER_BOARD_CI134;
 	else if (id == CI104J_ASIC_ID)
 		hwconf->board_type = MXSER_BOARD_CI104J;
 	else
@@ -2417,7 +2459,8 @@
 	(void) inb(port);
 	restore_flags(flags);
 	id = inb(port + 1) & 0x1F;
-	if ((id != C168_ASIC_ID) && (id != C104_ASIC_ID) && (id != CI104J_ASIC_ID))
+	if ((id != C168_ASIC_ID) && (id != C104_ASIC_ID) && (id != CI104J_ASIC_ID) &&
+		(id != C102_ASIC_ID) &&	(id != CI132_ASIC_ID) && (id != CI134_ASIC_ID))
 		return (-1);
 	for (i = 0, j = 0; i < 4; i++) {
 		n = inb(port + 2);
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index 79b5dfe..2dcd1ef 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -322,7 +322,7 @@
 		if (err)
 			break;
 
-		err = brw_kiovec(rw, 1, &iobuf, dev, &blocknr, sector_size);
+		err = brw_kiovec(rw, 1, &iobuf, raw_devices[minor].binding, &blocknr, sector_size);
 
 		if (rw == READ && err > 0)
 			mark_dirty_kiobuf(iobuf, err);
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 7eb8b68..d6710f5 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -42,10 +42,6 @@
 #include <linux/config.h>
 #include <linux/version.h>
 
-#ifdef CONFIG_PCI
-#define ENABLE_PCI
-#endif
-
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/major.h>
@@ -63,15 +59,8 @@
 #include <linux/fcntl.h>
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
-#ifdef ENABLE_PCI
 #include <linux/pci.h>
-#if (LINUX_VERSION_CODE < 0x020163) /* 2.1.99 */
-#include <linux/bios32.h>
-#endif
-#endif
-#if (LINUX_VERSION_CODE >= 131343) /* 2.1.15 -- XX get correct version */
 #include <linux/init.h>
-#endif
 	
 #include "rocket_int.h"
 #ifdef LOCAL_ROCKET_H
@@ -154,7 +143,6 @@
 static unsigned long time_counter;
 #endif
 
-#if ((LINUX_VERSION_CODE > 0x020111) && defined(MODULE))
 MODULE_AUTHOR("Theodore Ts'o");
 MODULE_DESCRIPTION("Comtrol Rocketport driver");
 MODULE_LICENSE("GPL");
@@ -170,39 +158,8 @@
 MODULE_PARM_DESC(controller, "I/O port for (ISA) rocketport controller");
 MODULE_PARM(support_low_speed, "i");
 MODULE_PARM_DESC(support_low_speed, "0 means support 50 baud, 1 means support 460400 baud");	
-#endif
 
-#if (LINUX_VERSION_CODE < 131336)
-int copy_from_user(void *to, const void *from_user, unsigned long len)
-{
-	int	error;
-
-	error = verify_area(VERIFY_READ, from_user, len);
-	if (error)
-		return len;
-	memcpy_fromfs(to, from_user, len);
-	return 0;
-}
-
-int copy_to_user(void *to_user, const void *from, unsigned long len)
-{
-	int	error;
-	
-	error = verify_area(VERIFY_WRITE, to_user, len);
-	if (error)
-		return len;
-	memcpy_tofs(to_user, from, len);
-	return 0;
-}
-
-static inline int signal_pending(struct task_struct *p)
-{
-	return (p->signal & ~p->blocked) != 0;
-}
-
-#else
 #include <asm/uaccess.h>
-#endif
 
 /*
  * tmp_buf is used as a temporary buffer by rp_write.  We need to
@@ -497,7 +454,7 @@
 			continue;
 		ctlp= sCtlNumToCtlPtr(ctrl);
 
-#ifdef ENABLE_PCI
+#ifdef CONFIG_PCI
 		if(ctlp->BusType == isPCI)
 			CtlMask= sPCIGetControllerIntStatus(ctlp);
 		else
@@ -611,12 +568,6 @@
 	rp_table[line] = info;
 }
 
-#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
-static int baud_table[] = {
-	0, 50, 75, 110, 134, 150, 200, 300,
-	600, 1200, 1800, 2400, 4800, 9600, 19200,
-	38400, 57600, 115200, 230400, 460800, 0 };
-#endif
 
 /*
  * This routine configures a rocketport port so according to its
@@ -627,9 +578,6 @@
 	unsigned cflag;
 	unsigned long 	flags;
 	int	bits, baud;
-#if (LINUX_VERSION_CODE < 131393) /* Linux 2.1.65 */
-	int i;
-#endif
 	CHANNEL_t	*cp;
 	
 	if (!info->tty || !info->tty->termios)
@@ -665,31 +613,9 @@
 	}
 	
 	/* baud rate */
-#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
-	i = cflag & CBAUD;
-	if (i & CBAUDEX) {
-		i &= ~CBAUDEX;
-		if (i < 1 || i > 4) 
-			info->tty->termios->c_cflag &= ~CBAUDEX;
-		else
-			i += 15;
-	}
-	if (i == 15) {
-		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
-			i += 1;
-		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
-			i += 2;
-		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
-			i += 3;
-		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
-			i += 4;
-	}
-	baud = baud_table[i] ? baud_table[i] : 9600;
-#else
 	baud = tty_get_baud_rate(info->tty);
 	if (!baud)
 		baud = 9600;
-#endif
 	info->cps = baud / bits;
 	sSetBaud(cp, (rp_baud_base/baud) - 1);
 	
@@ -990,7 +916,6 @@
 
 	info->flags |= ROCKET_INITIALIZED;
 
-#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
 	/*
 	 * Set up the tty->alt_speed kludge
 	 */
@@ -1002,7 +927,6 @@
 		info->tty->alt_speed = 230400;
 	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
 		info->tty->alt_speed = 460800;
-#endif
 
 	configure_r_port(info);
 	if (tty->termios->c_cflag & CBAUD) {
@@ -1094,10 +1018,8 @@
 	 * If transmission was throttled by the application request,
 	 * just flush the xmit buffer.
 	 */
-#if (LINUX_VERSION_CODE >= 131343)
 	if (tty->flow_stopped)
 		rp_flush_buffer(tty);
-#endif
 
 	/*
 	 * Wait for the transmit buffer to clear
@@ -1218,17 +1140,6 @@
 /*
  * Here are the routines used by rp_ioctl
  */
-#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
-static void send_break(	struct r_port * info, int duration)
-{
-	current->state = TASK_INTERRUPTIBLE;
-	cli();
-	sSendBreak(&info->channel);
-	schedule_timeout(duration);
-	sClrBreak(&info->channel);
-	sti();
-}
-#else
 static void rp_break(struct tty_struct *tty, int break_state)
 {
 	struct r_port * info = (struct r_port *)tty->driver_data;
@@ -1245,7 +1156,6 @@
 	}
 	restore_flags(flags);
 }
-#endif
 
 static int get_modem_info(struct r_port * info, unsigned int *value)
 {
@@ -1348,7 +1258,6 @@
 	info->close_delay = new_serial.close_delay;
 	info->closing_wait = new_serial.closing_wait;
 
-#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
 	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
 		info->tty->alt_speed = 57600;
 	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
@@ -1357,7 +1266,6 @@
 		info->tty->alt_speed = 230400;
 	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
 		info->tty->alt_speed = 460800;
-#endif
 	
 	configure_r_port(info);
 	return 0;
@@ -1389,54 +1297,13 @@
 		    unsigned int cmd, unsigned long arg)
 {
 	struct r_port * info = (struct r_port *)tty->driver_data;
-#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
-	int retval, tmp;
-#endif
 
 	if (cmd != RCKP_GET_PORTS &&
 	    rocket_paranoia_check(info, tty->device, "rp_ioctl"))
 		return -ENODEV;
 
 	switch (cmd) {
-#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
-		case TCSBRK:	/* SVID version: non-zero arg --> no break */
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			tty_wait_until_sent(tty, 0);
-			if (signal_pending(current))
-				return -EINTR;
-			if (!arg) {
-				send_break(info, HZ/4);	/* 1/4 second */
-				if (signal_pending(current))
-					return -EINTR;
-			}
-			return 0;
-		case TCSBRKP:	/* support for POSIX tcsendbreak() */
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			tty_wait_until_sent(tty, 0);
-			if (signal_pending(current))
-				return -EINTR;
-			send_break(info, arg ? arg*(HZ/10) : HZ/4);
-			if (signal_pending(current))
-				return -EINTR;
-			return 0;
-		case TIOCGSOFTCAR:
-			tmp = C_CLOCAL(tty) ? 1 : 0;
-			if (copy_to_user((void *)arg, &tmp, sizeof(int)))
-				return -EFAULT;
-			return 0;
-		case TIOCSSOFTCAR:
-			if (copy_from_user(&tmp, (void *)arg, sizeof(int)))
-				return -EFAULT;
 
-			tty->termios->c_cflag =
-				((tty->termios->c_cflag & ~CLOCAL) |
-				 (tmp ? CLOCAL : 0));
-			return 0;
-#endif
 		case TIOCMGET:
 			return get_modem_info(info, (unsigned int *) arg);
 		case TIOCMBIS:
@@ -1877,36 +1744,7 @@
 	sFlushTxFIFO(cp);
 }
 
-#ifdef ENABLE_PCI
-#if (LINUX_VERSION_CODE < 0x020163) /* 2.1.99 */
-/* For compatibility */
-static struct pci_dev *pci_find_slot(unsigned char bus,
-				     unsigned char device_fn)
-{
-	unsigned short		vendor_id, device_id;
-	int			ret, error;
-	static struct pci_dev	ret_struct;
-	
-	error = pcibios_read_config_word(bus, device_fn, PCI_VENDOR_ID,
-		&vendor_id);
-	ret = pcibios_read_config_word(bus, device_fn, PCI_DEVICE_ID,
-		&device_id);
-	if (error == 0)
-		error = ret;
-
-	if (error) {
-		printk("PCI RocketPort error: %s not initializing due to error"
-		       "reading configuration space\n",
-		       pcibios_strerror(error));
-		return(0);
-	}
-
-	memset(&ret_struct, 0, sizeof(ret_struct));
-	ret_struct.device = device_id;
-
-	return &ret_struct;
-}
-#endif
+#ifdef CONFIG_PCI
      
 int __init register_PCI(int i, unsigned int bus, unsigned int device_fn)
 {
@@ -1915,10 +1753,6 @@
 	char *str;
 	CONTROLLER_t	*ctlp;
 	struct pci_dev *dev = pci_find_slot(bus, device_fn);
-#if (LINUX_VERSION_CODE < 0x020163) /* 2.1.99 */
-	int	ret;
-	unsigned int port;
-#endif
 
 	if (!dev)
 		return 0;
@@ -2161,7 +1995,7 @@
 		if(init_ISA(i, &reserved_controller))
 			isa_boards_found++;
 	}
-#ifdef ENABLE_PCI
+#ifdef CONFIG_PCI
 	if (pcibios_present()) {
 		if(isa_boards_found < NUM_BOARDS)
 			pci_boards_found = init_PCI(isa_boards_found);
@@ -2219,13 +2053,9 @@
 	rocket_driver.stop = rp_stop;
 	rocket_driver.start = rp_start;
 	rocket_driver.hangup = rp_hangup;
-#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
 	rocket_driver.break_ctl = rp_break;
-#endif
-#if (LINUX_VERSION_CODE >= 131343)
 	rocket_driver.send_xchar = rp_send_xchar;
 	rocket_driver.wait_until_sent = rp_wait_until_sent;
-#endif
 
 	/*
 	 * The callout device is just like normal device except for
diff --git a/drivers/char/sbc60xxwdt.c b/drivers/char/sbc60xxwdt.c
index ff9a572..ac7aeda 100644
--- a/drivers/char/sbc60xxwdt.c
+++ b/drivers/char/sbc60xxwdt.c
@@ -109,6 +109,15 @@
 static int wdt_is_open;
 static int wdt_expect_close;
 
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
 /*
  *	Whack the dog
  */
@@ -202,6 +211,9 @@
 			/* Just in case we're already talking to someone... */
 			if(wdt_is_open)
 				return -EBUSY;
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			/* Good, fire up the show */
 			wdt_is_open = 1;
 			wdt_startup();
@@ -216,7 +228,7 @@
 {
 	if(minor(inode->i_rdev) == WATCHDOG_MINOR) 
 	{
-		if(wdt_expect_close)
+		if(wdt_expect_close && !nowayout)
 			wdt_turnoff();
 		else {
 			del_timer(&timer);
diff --git a/drivers/char/shwdt.c b/drivers/char/shwdt.c
index c636ecc..be73b1e 100644
--- a/drivers/char/shwdt.c
+++ b/drivers/char/shwdt.c
@@ -9,6 +9,9 @@
  * under the terms of the GNU General Public License as published by the
  * Free Software Foundation; either version 2 of the License, or (at your
  * option) any later version.
+ *
+ * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *     Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
  */
 #include <linux/config.h>
 #include <linux/module.h>
@@ -88,6 +91,15 @@
 static struct timer_list timer;
 static unsigned long next_heartbeat;
 
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
 /**
  *	sh_wdt_write_cnt - Write to Counter
  *
@@ -175,6 +187,10 @@
 			if (test_and_set_bit(0, &sh_is_open))
 				return -EBUSY;
 
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
+
 			sh_wdt_start();
 
 			break;
@@ -196,9 +212,9 @@
 static int sh_wdt_close(struct inode *inode, struct file *file)
 {
 	if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-		sh_wdt_stop();
-#endif
+		if (!nowayout) {
+			sh_wdt_stop();
+		}
 		clear_bit(0, &sh_is_open);
 	}
 	
diff --git a/drivers/char/softdog.c b/drivers/char/softdog.c
index 7635904..bbc0c8a 100644
--- a/drivers/char/softdog.c
+++ b/drivers/char/softdog.c
@@ -1,5 +1,5 @@
 /*
- *	SoftDog	0.05:	A Software Watchdog Device
+ *	SoftDog	0.06:	A Software Watchdog Device
  *
  *	(c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
  *				http://www.redhat.com
@@ -26,6 +26,10 @@
  *
  *  19980911 Alan Cox
  *	Made SMP safe for 2.3.x
+ *
+ *  20011214 Matt Domsch <Matt_Domsch@dell.com>
+ *      Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *      Didn't add timeout option, as soft_margin option already exists.
  */
  
 #include <linux/module.h>
@@ -46,6 +50,15 @@
 static int soft_margin = TIMER_MARGIN;	/* in seconds */
 
 MODULE_PARM(soft_margin,"i");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
 MODULE_LICENSE("GPL");
 
 /*
@@ -83,9 +96,9 @@
 {
 	if(timer_alive)
 		return -EBUSY;
-#ifdef CONFIG_WATCHDOG_NOWAYOUT	 
-	MOD_INC_USE_COUNT;
-#endif	
+	if (nowayout) {
+		MOD_INC_USE_COUNT;
+	}
 	/*
 	 *	Activate timer
 	 */
@@ -98,11 +111,11 @@
 {
 	/*
 	 *	Shut off the timer.
-	 * 	Lock it in if it's a module and we defined ...NOWAYOUT
+	 * 	Lock it in if it's a module and we set nowayout
 	 */
-#ifndef CONFIG_WATCHDOG_NOWAYOUT	 
-	del_timer(&watchdog_ticktock);
-#endif	
+	if(!nowayout) {
+		del_timer(&watchdog_ticktock);
+	}
 	timer_alive=0;
 	return 0;
 }
@@ -159,7 +172,7 @@
 	fops:		&softdog_fops,
 };
 
-static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.05, timer margin: %d sec\n";
+static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.06, soft_margin: %d sec, nowayout: %d\n";
 
 static int __init watchdog_init(void)
 {
@@ -170,7 +183,7 @@
 	if (ret)
 		return ret;
 
-	printk(banner, soft_margin);
+	printk(banner, soft_margin, nowayout);
 
 	return 0;
 }
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 92bc9c5..ced9b9e 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -109,25 +109,29 @@
         return result;
 }
 
-static void sonypi_ecrset(u16 addr, u16 value) {
+static void sonypi_ecrset(u8 addr, u8 value) {
 
-	wait_on_command(1, inw_p(SONYPI_CST_IOPORT) & 3);
-	outw_p(0x81, SONYPI_CST_IOPORT);
-	wait_on_command(0, inw_p(SONYPI_CST_IOPORT) & 2);
-	outw_p(addr, SONYPI_DATA_IOPORT);
-	wait_on_command(0, inw_p(SONYPI_CST_IOPORT) & 2);
-	outw_p(value, SONYPI_DATA_IOPORT);
-	wait_on_command(0, inw_p(SONYPI_CST_IOPORT) & 2);
+	wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3);
+	outb_p(0x81, SONYPI_CST_IOPORT);
+	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2);
+	outb_p(addr, SONYPI_DATA_IOPORT);
+	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2);
+	outb_p(value, SONYPI_DATA_IOPORT);
+	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2);
 }
 
-static u16 sonypi_ecrget(u16 addr) {
+static u8 sonypi_ecrget(u8 addr) {
 
-	wait_on_command(1, inw_p(SONYPI_CST_IOPORT) & 3);
-	outw_p(0x80, SONYPI_CST_IOPORT);
-	wait_on_command(0, inw_p(SONYPI_CST_IOPORT) & 2);
-	outw_p(addr, SONYPI_DATA_IOPORT);
-	wait_on_command(0, inw_p(SONYPI_CST_IOPORT) & 2);
-	return inw_p(SONYPI_DATA_IOPORT);
+	wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3);
+	outb_p(0x80, SONYPI_CST_IOPORT);
+	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2);
+	outb_p(addr, SONYPI_DATA_IOPORT);
+	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2);
+	return inb_p(SONYPI_DATA_IOPORT);
+}
+
+static u16 sonypi_ecrget16(u8 addr) {
+	return sonypi_ecrget(addr) | (sonypi_ecrget(addr + 1) << 8);
 }
 
 /* Initializes the device - this comes from the AML code in the ACPI bios */
@@ -286,19 +290,38 @@
 	sonypi_device.camera_power = 1;
 }
 
+/* sets the bluetooth subsystem power state */
+static void sonypi_setbluetoothpower(u8 state) {
+
+	state = (state != 0);
+	if (sonypi_device.bluetooth_power && state) 
+		return;
+	if (!sonypi_device.bluetooth_power && !state) 
+		return;
+	
+	sonypi_call2(0x96, state);
+	sonypi_call1(0x93);
+	sonypi_device.bluetooth_power = state;
+}
+
 /* Interrupt handler: some event is available */
 void sonypi_irq(int irq, void *dev_id, struct pt_regs *regs) {
 	u8 v1, v2, event = 0;
 	int i;
 	u8 sonypi_jogger_ev, sonypi_fnkey_ev;
+	u8 sonypi_capture_ev, sonypi_bluetooth_ev;
 
 	if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) {
 		sonypi_jogger_ev = SONYPI_TYPE2_JOGGER_EV;
 		sonypi_fnkey_ev = SONYPI_TYPE2_FNKEY_EV;
+		sonypi_capture_ev = SONYPI_TYPE2_CAPTURE_EV;
+		sonypi_bluetooth_ev = SONYPI_TYPE2_BLUETOOTH_EV;
 	}
 	else {
 		sonypi_jogger_ev = SONYPI_TYPE1_JOGGER_EV;
 		sonypi_fnkey_ev = SONYPI_TYPE1_FNKEY_EV;
+		sonypi_capture_ev = SONYPI_TYPE1_CAPTURE_EV;
+		sonypi_bluetooth_ev = SONYPI_TYPE1_BLUETOOTH_EV;
 	}
 
 	v1 = inb_p(sonypi_device.ioport1);
@@ -318,7 +341,7 @@
 				goto found;
 			}
 	}
-	if ((v2 & SONYPI_CAPTURE_EV) == SONYPI_CAPTURE_EV) {
+	if ((v2 & sonypi_capture_ev) == sonypi_capture_ev) {
 		for (i = 0; sonypi_captureev[i].event; i++)
 			if (sonypi_captureev[i].data == v1) {
 				event = sonypi_captureev[i].event;
@@ -332,7 +355,7 @@
 				goto found;
 			}
 	}
-	if ((v2 & SONYPI_BLUETOOTH_EV) == SONYPI_BLUETOOTH_EV) {
+	if ((v2 & sonypi_bluetooth_ev) == sonypi_bluetooth_ev) {
 		for (i = 0; sonypi_blueev[i].event; i++)
 			if (sonypi_blueev[i].data == v1) {
 				event = sonypi_blueev[i].event;
@@ -510,24 +533,74 @@
 static int sonypi_misc_ioctl(struct inode *ip, struct file *fp, 
 			     unsigned int cmd, unsigned long arg) {
 	int ret = 0;
-	u8 val;
+	u8 val8;
+	u16 val16;
 
 	down(&sonypi_device.lock);
 	switch (cmd) {
-		case SONYPI_IOCGBRT:
-			val = sonypi_ecrget(0x96) & 0xff;
-			if (copy_to_user((u8 *)arg, &val, sizeof(val))) {
-				ret = -EFAULT;
-				goto out;
-			}
-			break;
-		case SONYPI_IOCSBRT:
-			if (copy_from_user(&val, (u8 *)arg, sizeof(val))) {
-				ret = -EFAULT;
-				goto out;
-			}
-			sonypi_ecrset(0x96, val);
-			break;
+	case SONYPI_IOCGBRT:
+		val8 = sonypi_ecrget(0x96);
+		if (copy_to_user((u8 *)arg, &val8, sizeof(val8))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		break;
+	case SONYPI_IOCSBRT:
+		if (copy_from_user(&val8, (u8 *)arg, sizeof(val8))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		sonypi_ecrset(0x96, val8);
+		break;
+	case SONYPI_IOCGBAT1CAP:
+		val16 = sonypi_ecrget16(0xb2);
+		if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		break;
+	case SONYPI_IOCGBAT1REM:
+		val16 = sonypi_ecrget16(0xa2);
+		if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		break;
+	case SONYPI_IOCGBAT2CAP:
+		val16 = sonypi_ecrget16(0xba);
+		if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		break;
+	case SONYPI_IOCGBAT2REM:
+		val16 = sonypi_ecrget16(0xaa);
+		if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		break;
+	case SONYPI_IOCGBATFLAGS:
+		val8 = sonypi_ecrget(0x81) & 0x07;
+		if (copy_to_user((u8 *)arg, &val8, sizeof(val8))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		break;
+	case SONYPI_IOCGBLUE:
+		val8 = sonypi_device.bluetooth_power;
+		if (copy_to_user((u8 *)arg, &val8, sizeof(val8))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		break;
+	case SONYPI_IOCSBLUE:
+		if (copy_from_user(&val8, (u8 *)arg, sizeof(val8))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		sonypi_setbluetoothpower(val8);
+		break;
 	default:
 		ret = -EINVAL;
 	}
@@ -562,6 +635,7 @@
 		sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2;
 	sonypi_initq();
 	init_MUTEX(&sonypi_device.lock);
+	sonypi_device.bluetooth_power = 0;
 	
 	if (pcidev && pci_enable_device(pcidev)) {
 		printk(KERN_ERR "sonypi: pci_enable_device failed\n");
diff --git a/drivers/char/sonypi.h b/drivers/char/sonypi.h
index 9d83608..3937c1e 100644
--- a/drivers/char/sonypi.h
+++ b/drivers/char/sonypi.h
@@ -34,8 +34,8 @@
 
 #ifdef __KERNEL__
 
-#define SONYPI_DRIVER_MAJORVERSION	1
-#define SONYPI_DRIVER_MINORVERSION	8
+#define SONYPI_DRIVER_MAJORVERSION	 1
+#define SONYPI_DRIVER_MINORVERSION	10
 
 #include <linux/types.h>
 #include <linux/pci.h>
@@ -132,15 +132,17 @@
 #define SONYPI_CAMERA_ROMVERSION 		9
 
 /* key press event data (ioport2) */
-#define SONYPI_TYPE1_JOGGER_EV	0x10
-#define SONYPI_TYPE2_JOGGER_EV	0x08
-#define SONYPI_CAPTURE_EV	0x60
-#define SONYPI_TYPE1_FNKEY_EV	0x20
-#define SONYPI_TYPE2_FNKEY_EV	0x08
-#define SONYPI_BLUETOOTH_EV	0x30
-#define SONYPI_TYPE1_PKEY_EV	0x40
-#define SONYPI_BACK_EV		0x08
-#define SONYPI_LID_EV		0x38
+#define SONYPI_TYPE1_JOGGER_EV		0x10
+#define SONYPI_TYPE2_JOGGER_EV		0x08
+#define SONYPI_TYPE1_CAPTURE_EV		0x60
+#define SONYPI_TYPE2_CAPTURE_EV		0x08
+#define SONYPI_TYPE1_FNKEY_EV		0x20
+#define SONYPI_TYPE2_FNKEY_EV		0x08
+#define SONYPI_TYPE1_BLUETOOTH_EV	0x30
+#define SONYPI_TYPE2_BLUETOOTH_EV	0x08
+#define SONYPI_TYPE1_PKEY_EV		0x40
+#define SONYPI_BACK_EV			0x08
+#define SONYPI_LID_EV			0x38
 
 struct sonypi_event {
 	u8	data;
@@ -203,6 +205,8 @@
 /* The set of possible bluetooth events */
 static struct sonypi_event sonypi_blueev[] = {
 	{ 0x55, SONYPI_EVENT_BLUETOOTH_PRESSED },
+	{ 0x59, SONYPI_EVENT_BLUETOOTH_ON },
+	{ 0x5a, SONYPI_EVENT_BLUETOOTH_OFF },
 	{ 0x00, 0x00 }
 };
 
@@ -241,6 +245,7 @@
 	u16 ioport2;
 	u16 region_size;
 	int camera_power;
+	int bluetooth_power;
 	struct semaphore lock;
 	struct sonypi_queue queue;
 	int open_count;
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 80a73a1..db06f5a 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -2458,7 +2458,7 @@
 	}
 
 /*
- *	We have verfied that the board is actually present, so now we
+ *	We have verified that the board is actually present, so now we
  *	can complete the setup.
  */
 
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index de1c67b..c50bc72 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -925,9 +925,9 @@
 static char *driver_name = "SyncLink serial driver";
 static char *driver_version = "$Revision: 3.12 $";
 
-static int __init synclink_init_one (struct pci_dev *dev,
+static int synclink_init_one (struct pci_dev *dev,
 				     const struct pci_device_id *ent);
-static void __exit synclink_remove_one (struct pci_dev *dev);
+static void synclink_remove_one (struct pci_dev *dev);
 
 static struct pci_device_id synclink_pci_tbl[] __devinitdata = {
 	{ PCI_VENDOR_ID_MICROGATE, PCI_DEVICE_ID_MICROGATE_USC, PCI_ANY_ID, PCI_ANY_ID, },
diff --git a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c
index 4e5cfcf..24b4906 100644
--- a/drivers/char/tpqic02.c
+++ b/drivers/char/tpqic02.c
@@ -2748,7 +2748,9 @@
 	 * the config parameters have been set using MTSETCONFIG.
 	 */
 
-	if (check_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE)) {
+	/* Grab the IO region. */
+	if (!request_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE,
+			   TPQIC02_NAME)) {
 		printk(TPQIC02_NAME
 		       ": IO space at 0x%x [%d ports] already reserved\n",
 		       QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE);
@@ -2762,6 +2764,7 @@
 		printk(TPQIC02_NAME
 		       ": can't allocate IRQ%d for QIC-02 tape\n",
 		       QIC02_TAPE_IRQ);
+		release_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE);
 		return -EBUSY;
 	}
 
@@ -2771,13 +2774,10 @@
 		       ": can't allocate DMA%d for QIC-02 tape\n",
 		       QIC02_TAPE_DMA);
 		free_irq(QIC02_TAPE_IRQ, NULL);
+		release_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE);
 		return -EBUSY;
 	}
 
-	/* Grab the IO region. We already made sure it's available. */
-	request_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE,
-		       TPQIC02_NAME);
-
 	/* Setup the page-address for the dma transfer. */
 	buffaddr =
 	    (void *) __get_dma_pages(GFP_KERNEL, get_order(TPQBUF_SIZE));
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 9fdd57e..d77cfdb2 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -569,6 +569,8 @@
 	struct task_struct *p;
 	int tty_pgrp = -1;
 
+	lock_kernel();
+
 	if (tty) {
 		tty_pgrp = tty->pgrp;
 		if (on_exit && tty->driver.type != TTY_DRIVER_TYPE_PTY)
@@ -578,6 +580,7 @@
 			kill_pg(current->tty_old_pgrp, SIGHUP, on_exit);
 			kill_pg(current->tty_old_pgrp, SIGCONT, on_exit);
 		}
+		unlock_kernel();	
 		return;
 	}
 	if (tty_pgrp > 0) {
@@ -595,6 +598,7 @@
 	  	if (p->session == current->session)
 			p->tty = NULL;
 	read_unlock(&tasklist_lock);
+	unlock_kernel();
 }
 
 void stop_tty(struct tty_struct *tty)
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
index 45bbbc7..c59fc29 100644
--- a/drivers/char/vme_scc.c
+++ b/drivers/char/vme_scc.c
@@ -214,7 +214,7 @@
 {
 	struct scc_port *port;
 
-	printk("SCC: MVME147 Serial Driver\n");
+	printk(KERN_INFO "SCC: MVME147 Serial Driver\n");
 	/* Init channel A */
 	port = &scc_ports[0];
 	port->channel = CHANNEL_A;
@@ -284,7 +284,7 @@
 	if (!(mvme16x_config & MVME16x_CONFIG_GOT_SCCA))
 		return (-ENODEV);
 
-	printk("SCC: MVME162 Serial Driver\n");
+	printk(KERN_INFO "SCC: MVME162 Serial Driver\n");
 	/* Init channel A */
 	port = &scc_ports[0];
 	port->channel = CHANNEL_A;
@@ -352,7 +352,7 @@
 {
 	struct scc_port *port;
 
-	printk("SCC: BVME6000 Serial Driver\n");
+	printk(KERN_INFO "SCC: BVME6000 Serial Driver\n");
 	/* Init channel A */
 	port = &scc_ports[0];
 	port->channel = CHANNEL_A;
@@ -449,7 +449,7 @@
 
 	ch = SCCread_NB(RX_DATA_REG);
 	if (!tty) {
-		printk ("scc_rx_int with NULL tty!\n");
+		printk(KERN_WARNING "scc_rx_int with NULL tty!\n");
 		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
 		return;
 	}
@@ -487,7 +487,7 @@
 	SCC_ACCESS_INIT(port);
 	
 	if (!tty) {
-		printk ("scc_spcond_int with NULL tty!\n");
+		printk(KERN_WARNING "scc_spcond_int with NULL tty!\n");
 		SCCwrite(COMMAND_REG, CR_ERROR_RESET);
 		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
 		return;
@@ -533,7 +533,7 @@
 	SCC_ACCESS_INIT(port);
 
 	if (!port->gs.tty) {
-		printk ("scc_tx_int with NULL tty!\n");
+		printk(KERN_WARNING "scc_tx_int with NULL tty!\n");
 		SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
 		SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);
 		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
@@ -719,7 +719,7 @@
 	else if ((MACH_IS_MVME16x && (baud < 50 || baud > 38400)) ||
 		 (MACH_IS_MVME147 && (baud < 50 || baud > 19200)) ||
 		 (MACH_IS_BVME6000 &&(baud < 50 || baud > 76800))) {
-		printk("SCC: Bad speed requested, %d\n", baud);
+		printk(KERN_NOTICE "SCC: Bad speed requested, %d\n", baud);
 		return 0;
 	}
 
diff --git a/drivers/char/wdt.c b/drivers/char/wdt.c
index f98face..1fb85c7 100644
--- a/drivers/char/wdt.c
+++ b/drivers/char/wdt.c
@@ -15,7 +15,7 @@
  *
  *	(c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
  *
- *	Release 0.08.
+ *	Release 0.09.
  *
  *	Fixes
  *		Dave Gregorich	:	Modularisation and minor bugs
@@ -27,6 +27,7 @@
  *		Tim Hockin	:	Added insmod parameters, comment cleanup
  *					Parameterized timeout
  *		Tigran Aivazian	:	Restructured wdt_init() to handle failures
+ *		Matt Domsch	:	added nowayout and timeout module options
  */
 
 #include <linux/config.h>
@@ -62,6 +63,26 @@
 
 #define WD_TIMO (100*60)		/* 1 minute */
 
+static int timeout_val = WD_TIMO;	/* value passed to card */
+static int timeout = 60;	        /* in seconds */
+MODULE_PARM(timeout,"i");
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+static void __init
+wdt_validate_timeout(void)
+{
+	timeout_val = timeout * 100;
+}
+
 #ifndef MODULE
 
 /**
@@ -216,7 +237,7 @@
 	/* Write a watchdog value */
 	inb_p(WDT_DC);
 	wdt_ctr_mode(1,2);
-	wdt_ctr_load(1,WD_TIMO);		/* Timeout */
+	wdt_ctr_load(1,timeout_val);		/* Timeout */
 	outb_p(0, WDT_DC);
 }
 
@@ -339,6 +360,9 @@
 		case WATCHDOG_MINOR:
 			if(test_and_set_bit(0, &wdt_is_open))
 				return -EBUSY;
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			/*
 			 *	Activate 
 			 */
@@ -348,7 +372,7 @@
 			wdt_ctr_mode(1,2);
 			wdt_ctr_mode(2,0);
 			wdt_ctr_load(0, 8948);		/* count at 100Hz */
-			wdt_ctr_load(1,WD_TIMO);	/* Timeout 120 seconds */
+			wdt_ctr_load(1,timeout_val);	/* Timeout */
 			wdt_ctr_load(2,65535);
 			outb_p(0, WDT_DC);	/* Enable */
 			return 0;
@@ -375,10 +399,10 @@
 {
 	if(minor(inode->i_rdev)==WATCHDOG_MINOR)
 	{
-#ifndef CONFIG_WATCHDOG_NOWAYOUT	
-		inb_p(WDT_DC);		/* Disable counters */
-		wdt_ctr_load(2,0);	/* 0 length reset pulses now */
-#endif		
+		if (!nowayout) {
+			inb_p(WDT_DC);		/* Disable counters */
+			wdt_ctr_load(2,0);	/* 0 length reset pulses now */
+		}
 		clear_bit(0, &wdt_is_open);
 	}
 	return 0;
@@ -484,6 +508,7 @@
 {
 	int ret;
 
+	wdt_validate_timeout();
 	ret = misc_register(&wdt_miscdev);
 	if (ret) {
 		printk(KERN_ERR "wdt: can't misc_register on minor=%d\n", WATCHDOG_MINOR);
diff --git a/drivers/char/wdt977.c b/drivers/char/wdt977.c
index 7f9dde0..0e32706 100644
--- a/drivers/char/wdt977.c
+++ b/drivers/char/wdt977.c
@@ -1,5 +1,5 @@
 /*
- *	Wdt977	0.01:	A Watchdog Device for Netwinder W83977AF chip
+ *	Wdt977	0.02:	A Watchdog Device for Netwinder W83977AF chip
  *
  *	(c) Copyright 1998 Rebel.com (Woody Suwalski <woody@netwinder.org>)
  *
@@ -11,8 +11,13 @@
  *	2 of the License, or (at your option) any later version.
  *
  *			-----------------------
+ *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *           Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *	19-Dec-2001 Woody Suwalski: Netwinder fixes, ioctl interface
+ *	06-Jan-2002 Woody Suwalski: For compatibility, convert all timeouts
+ *				    from minutes to seconds.
  */
- 
+
 #include <linux/module.h>
 #include <linux/config.h>
 #include <linux/types.h>
@@ -21,56 +26,123 @@
 #include <linux/miscdevice.h>
 #include <linux/init.h>
 #include <linux/smp_lock.h>
+#include <linux/watchdog.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/mach-types.h>
+#include <asm/uaccess.h>
 
 #define WATCHDOG_MINOR	130
 
-static	int timeout = 3;
+#define	DEFAULT_TIMEOUT	1	/* default timeout = 1 minute */
+
+static	int timeout = DEFAULT_TIMEOUT*60;	/* TO in seconds from user */
+static	int timeoutM = DEFAULT_TIMEOUT;		/* timeout in minutes */
 static	int timer_alive;
 static	int testmode;
 
+MODULE_PARM(timeout, "i");
+MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (60..15300), default=60");
+MODULE_PARM(testmode, "i");
+MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+
+/* This is kicking the watchdog by simply re-writing the timeout to reg. 0xF2 */
+int kick_wdog(void)
+{
+	/*
+	 *	Refresh the timer.
+	 */
+
+	/* unlock the SuperIO chip */
+	outb(0x87,0x370);
+	outb(0x87,0x370);
+
+	/* select device Aux2 (device=8) and kicks watchdog reg F2 */
+	/* F2 has the timeout in minutes */
+
+	outb(0x07,0x370);
+	outb(0x08,0x371);
+	outb(0xF2,0x370);
+	outb(timeoutM,0x371);
+
+	/* lock the SuperIO chip */
+	outb(0xAA,0x370);
+
+	return 0;
+}
+
+
 /*
  *	Allow only one person to hold it open
  */
- 
+
 static int wdt977_open(struct inode *inode, struct file *file)
 {
+
 	if(timer_alive)
 		return -EBUSY;
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
-	MOD_INC_USE_COUNT;
-#endif
+
+	/* convert seconds to minutes, rounding up */
+	timeoutM = timeout + 59;
+	timeoutM /= 60;
+
+	if (nowayout)
+	{
+		MOD_INC_USE_COUNT;
+
+		/* do not permit disabling the watchdog by writing 0 to reg. 0xF2 */
+		if (!timeoutM) timeoutM = DEFAULT_TIMEOUT;
+	}
 	timer_alive++;
 
-	//max timeout value = 255 minutes (0xFF). Write 0 to disable WatchDog.
-	if (timeout>255)
-	    timeout = 255;
+	if (machine_is_netwinder())
+	{
+		/* we have a hw bug somewhere, so each 977 minute is actually only 30sec
+		 *  this limits the max timeout to half of device max of 255 minutes...
+		 */
+		timeoutM += timeoutM;
+	}
 
-	printk(KERN_INFO "Watchdog: active, current timeout %d min.\n",timeout);
+	/* max timeout value = 255 minutes (0xFF). Write 0 to disable WatchDog. */
+	if (timeoutM > 255) timeoutM = 255;
 
-	// unlock the SuperIO chip
-	outb(0x87,0x370); 
-	outb(0x87,0x370); 
-	
-	//select device Aux2 (device=8) and set watchdog regs F2, F3 and F4
-	//F2 has the timeout in minutes
-	//F3 could be set to the POWER LED blink (with GP17 set to PowerLed)
-	//   at timeout, and to reset timer on kbd/mouse activity (not now)
-	//F4 is used to just clear the TIMEOUT'ed state (bit 0)
-	
+	/* convert seconds to minutes */
+	printk(KERN_INFO "Wdt977 Watchdog activated: timeout = %d sec, nowayout = %i, testmode = %i.\n",
+		machine_is_netwinder() ? (timeoutM>>1)*60 : timeoutM*60,
+		nowayout, testmode);
+
+	/* unlock the SuperIO chip */
+	outb(0x87,0x370);
+	outb(0x87,0x370);
+
+	/* select device Aux2 (device=8) and set watchdog regs F2, F3 and F4
+	 * F2 has the timeout in minutes
+	 * F3 could be set to the POWER LED blink (with GP17 set to PowerLed)
+	 *   at timeout, and to reset timer on kbd/mouse activity (not impl.)
+	 * F4 is used to just clear the TIMEOUT'ed state (bit 0)
+	 */
 	outb(0x07,0x370);
 	outb(0x08,0x371);
 	outb(0xF2,0x370);
-	outb(timeout,0x371);
+	outb(timeoutM,0x371);
 	outb(0xF3,0x370);
-	outb(0x00,0x371);	//another setting is 0E for kbd/mouse/LED
+	outb(0x00,0x371);	/* another setting is 0E for kbd/mouse/LED */
 	outb(0xF4,0x370);
 	outb(0x00,0x371);
-	
-	//at last select device Aux1 (dev=7) and set GP16 as a watchdog output
+
+	/* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */
+	/* in test mode watch the bit 1 on F4 to indicate "triggered" */
 	if (!testmode)
 	{
 		outb(0x07,0x370);
@@ -78,9 +150,9 @@
 		outb(0xE6,0x370);
 		outb(0x08,0x371);
 	}
-		
-	// lock the SuperIO chip
-	outb(0xAA,0x370); 
+
+	/* lock the SuperIO chip */
+	outb(0xAA,0x370);
 
 	return 0;
 }
@@ -89,84 +161,163 @@
 {
 	/*
 	 *	Shut off the timer.
-	 * 	Lock it in if it's a module and we defined ...NOWAYOUT
+	 * 	Lock it in if it's a module and we set nowayout
 	 */
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
+	if (!nowayout)
+	{
+		lock_kernel();
 
-	// unlock the SuperIO chip
-	outb(0x87,0x370); 
-	outb(0x87,0x370); 
-	
-	//select device Aux2 (device=8) and set watchdog regs F2,F3 and F4
-	//F3 is reset to its default state
-	//F4 can clear the TIMEOUT'ed state (bit 0) - back to default
-	//We can not use GP17 as a PowerLed, as we use its usage as a RedLed
-	
-	outb(0x07,0x370);
-	outb(0x08,0x371);
-	outb(0xF2,0x370);
-	outb(0xFF,0x371);
-	outb(0xF3,0x370);
-	outb(0x00,0x371);
-	outb(0xF4,0x370);
-	outb(0x00,0x371);
-	outb(0xF2,0x370);
-	outb(0x00,0x371);
-	
-	//at last select device Aux1 (dev=7) and set GP16 as a watchdog output
-	outb(0x07,0x370);
-	outb(0x07,0x371);
-	outb(0xE6,0x370);
-	outb(0x08,0x371);
-	
-	// lock the SuperIO chip
-	outb(0xAA,0x370);
+		/* unlock the SuperIO chip */
+		outb(0x87,0x370);
+		outb(0x87,0x370);
 
-	timer_alive=0;
+		/* select device Aux2 (device=8) and set watchdog regs F2,F3 and F4
+		* F3 is reset to its default state
+		* F4 can clear the TIMEOUT'ed state (bit 0) - back to default
+		* We can not use GP17 as a PowerLed, as we use its usage as a RedLed
+		*/
+		outb(0x07,0x370);
+		outb(0x08,0x371);
+		outb(0xF2,0x370);
+		outb(0xFF,0x371);
+		outb(0xF3,0x370);
+		outb(0x00,0x371);
+		outb(0xF4,0x370);
+		outb(0x00,0x371);
+		outb(0xF2,0x370);
+		outb(0x00,0x371);
 
-	printk(KERN_INFO "Watchdog: shutdown.\n");
-#endif
+		/* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */
+		outb(0x07,0x370);
+		outb(0x07,0x371);
+		outb(0xE6,0x370);
+		outb(0x08,0x371);
+
+		/* lock the SuperIO chip */
+		outb(0xAA,0x370);
+
+		timer_alive=0;
+		unlock_kernel();
+
+		printk(KERN_INFO "Wdt977 Watchdog: shutdown\n");
+	}
 	return 0;
 }
 
-static ssize_t wdt977_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+
+/*
+ *      wdt977_write:
+ *      @file: file handle to the watchdog
+ *      @buf: buffer to write (unused as data does not matter here
+ *      @count: count of bytes
+ *      @ppos: pointer to the position to write. No seeks allowed
+ *
+ *      A write to a watchdog device is defined as a keepalive signal. Any
+ *      write of data will do, as we we don't define content meaning.
+ */
+
+static ssize_t wdt977_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
 {
+	/*  Can't seek (pwrite) on this device  */
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
 
-	//max timeout value = 255 minutes (0xFF). Write 0 to disable WatchDog.
-	if (timeout>255)
-	    timeout = 255;
-
-	/*
-	 *	Refresh the timer.
-	 */
-		
-	//we have a hw bug somewhere, so each 977 minute is actually only 30sec
-	//as such limit the max timeout to half of max of 255 minutes...
-//	if (timeout>126)
-//	    timeout = 126;
-	
-	// unlock the SuperIO chip
-	outb(0x87,0x370); 
-	outb(0x87,0x370); 
-	
-	//select device Aux2 (device=8) and kicks watchdog reg F2
-	//F2 has the timeout in minutes
-	
-	outb(0x07,0x370);
-	outb(0x08,0x371);
-	outb(0xF2,0x370);
-	outb(timeout,0x371);
-	
-	// lock the SuperIO chip
-	outb(0xAA,0x370); 
-	
-	return 1;
+	if(count)
+	{
+		kick_wdog();
+		return 1;
+	}
+	return 0;
 }
 
+/*
+ *      wdt977_ioctl:
+ *      @inode: inode of the device
+ *      @file: file handle to the device
+ *      @cmd: watchdog command
+ *      @arg: argument pointer
+ *
+ *      The watchdog API defines a common set of functions for all watchdogs
+ *      according to their available features.
+ */
+
+static int wdt977_ioctl(struct inode *inode, struct file *file,
+         unsigned int cmd, unsigned long arg)
+{
+static struct watchdog_info ident = {
+	identity	: "Winbond 83977"
+};
+
+int temp;
+
+	switch(cmd)
+	{
+	default:
+		return -ENOTTY;
+
+	case WDIOC_GETSUPPORT:
+	    return copy_to_user((struct watchdog_info *)arg, &ident,
+			sizeof(ident)) ? -EFAULT : 0;
+
+	case WDIOC_GETBOOTSTATUS:
+		return put_user(0, (int *) arg);
+
+	case WDIOC_GETSTATUS:
+		/* unlock the SuperIO chip */
+		outb(0x87,0x370);
+		outb(0x87,0x370);
+
+		/* select device Aux2 (device=8) and read watchdog reg F4 */
+		outb(0x07,0x370);
+		outb(0x08,0x371);
+		outb(0xF4,0x370);
+		temp = inb(0x371);
+
+		/* lock the SuperIO chip */
+		outb(0xAA,0x370);
+
+		/* return info if "expired" in test mode */
+		return put_user(temp & 1, (int *) arg);
+
+	case WDIOC_KEEPALIVE:
+		kick_wdog();
+		return 0;
+
+	case WDIOC_SETTIMEOUT:
+		if (copy_from_user(&temp, (int *) arg, sizeof(int)))
+			return -EFAULT;
+
+		/* convert seconds to minutes, rounding up */
+		temp += 59;
+		temp /= 60;
+
+		/* we have a hw bug somewhere, so each 977 minute is actually only 30sec
+		*  this limits the max timeout to half of device max of 255 minutes...
+		*/
+		if (machine_is_netwinder())
+		{
+		    temp += temp;
+		}
+
+		/* Sanity check */
+		if (temp < 0 || temp > 255)
+			return -EINVAL;
+
+		if (!temp && nowayout)
+			return -EINVAL;
+
+		timeoutM = temp;
+		kick_wdog();
+		return 0;
+	}
+}
+
+
 static struct file_operations wdt977_fops=
 {
 	owner:		THIS_MODULE,
 	write:		wdt977_write,
+	ioctl:		wdt977_ioctl,
 	open:		wdt977_open,
 	release:	wdt977_release,
 };
@@ -184,9 +335,9 @@
 		return -ENODEV;
 
 	misc_register(&wdt977_miscdev);
-	printk(KERN_INFO "NetWinder Watchdog sleeping.\n");
+	printk(KERN_INFO "Wdt977 Watchdog sleeping.\n");
 	return 0;
-}	
+}
 
 static void __exit nwwatchdog_exit(void)
 {
diff --git a/drivers/char/wdt_pci.c b/drivers/char/wdt_pci.c
index 9097fe9..62d3ffef 100644
--- a/drivers/char/wdt_pci.c
+++ b/drivers/char/wdt_pci.c
@@ -15,7 +15,7 @@
  *
  *	(c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
  *
- *	Release 0.08.
+ *	Release 0.09.
  *
  *	Fixes
  *		Dave Gregorich	:	Modularisation and minor bugs
@@ -30,6 +30,7 @@
  *		Alan Cox	:	Split ISA and PCI cards into two drivers
  *		Jeff Garzik	:	PCI cleanups
  *		Tigran Aivazian	:	Restructured wdtpci_init_one() to handle failures
+ *		Matt Domsch	:	added nowayout and timeout module options
  */
 
 #include <linux/config.h>
@@ -83,6 +84,26 @@
 
 #define WD_TIMO (100*60)		/* 1 minute */
 
+static int timeout_val = WD_TIMO;	/* value passed to card */
+static int timeout = 60;	        /* in seconds */
+MODULE_PARM(timeout,"i");
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+static void __init
+wdtpci_validate_timeout(void)
+{
+	timeout_val = timeout * 100;
+}
+
 #ifndef MODULE
 
 /**
@@ -232,7 +253,7 @@
 	/* Write a watchdog value */
 	inb_p(WDT_DC);
 	wdtpci_ctr_mode(1,2);
-	wdtpci_ctr_load(1,WD_TIMO);		/* Timeout */
+	wdtpci_ctr_load(1,timeout_val);		/* Timeout */
 	outb_p(0, WDT_DC);
 }
 
@@ -357,9 +378,9 @@
 			{
 				return -EBUSY;
 			}
-#ifdef CONFIG_WATCHDOG_NOWAYOUT	
-			MOD_INC_USE_COUNT;
-#endif
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			/*
 			 *	Activate 
 			 */
@@ -385,7 +406,7 @@
 			wdtpci_ctr_mode(1,2);
 			wdtpci_ctr_mode(2,1);
 			wdtpci_ctr_load(0,20833);	/* count at 100Hz */
-			wdtpci_ctr_load(1,WD_TIMO);/* Timeout 60 seconds */
+			wdtpci_ctr_load(1,timeout_val); /* Timeout */
 			/* DO NOT LOAD CTR2 on PCI card! -- JPN */
 			outb_p(0, WDT_DC);	/* Enable */
 			return 0;
@@ -412,10 +433,10 @@
 {
 	if(minor(inode->i_rdev)==WATCHDOG_MINOR)
 	{
-#ifndef CONFIG_WATCHDOG_NOWAYOUT	
-		inb_p(WDT_DC);		/* Disable counters */
-		wdtpci_ctr_load(2,0);	/* 0 length reset pulses now */
-#endif		
+		if (!nowayout) {
+			inb_p(WDT_DC);		/* Disable counters */
+			wdtpci_ctr_load(2,0);	/* 0 length reset pulses now */
+		}
 		clear_bit(0, &wdt_is_open );
 	}
 	return 0;
@@ -617,6 +638,8 @@
 	
 	if (rc < 1)
 		return -ENODEV;
+
+	wdtpci_validate_timeout();
 	
 	return 0;
 }
diff --git a/drivers/fc4/soc.c b/drivers/fc4/soc.c
index 19aee06..796c219 100644
--- a/drivers/fc4/soc.c
+++ b/drivers/fc4/soc.c
@@ -742,7 +742,6 @@
 	
 	for_each_soc(s) {
 		irq = s->port[0].fc.irq;
-		disable_irq (irq);
 		free_irq (irq, s);
 
 		fcp_release(&(s->port[0].fc), 2);
diff --git a/drivers/fc4/socal.c b/drivers/fc4/socal.c
index 447a4de..c923d5c 100644
--- a/drivers/fc4/socal.c
+++ b/drivers/fc4/socal.c
@@ -881,7 +881,6 @@
 	
 	for_each_socal(s) {
 		irq = s->port[0].fc.irq;
-		disable_irq (irq);
 		free_irq (irq, s);
 
 		fcp_release(&(s->port[0].fc), 2);
diff --git a/drivers/i2c/i2c-algo-bit.c b/drivers/i2c/i2c-algo-bit.c
index a576ffe..e8e2fe6 100644
--- a/drivers/i2c/i2c-algo-bit.c
+++ b/drivers/i2c/i2c-algo-bit.c
@@ -49,7 +49,7 @@
 /* respectively. This makes sure that the algorithm works. Some chips   */
 /* might not like this, as they have an internal timeout of some mils	*/
 /*
-#define SLO_IO      jif=jiffies;while(jiffies<=jif+i2c_table[minor].veryslow)\
+#define SLO_IO      jif=jiffies;while(time_before_eq(jiffies, jif+i2c_table[minor].veryslow))\
                         cond_resched();
 */
 
@@ -117,7 +117,7 @@
  		 * while they are processing data internally. 
  		 */
 		setscl(adap,1);
-		if (start+adap->timeout <= jiffies) {
+		if (time_after_eq(jiffies, start+adap->timeout)) {
 			return -ETIMEDOUT;
 		}
 		cond_resched();
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 3b001b5..0ce05f1 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -141,7 +141,7 @@
 #ifdef DEBUG
 	struct inode *inode = file->f_dentry->d_inode;
 	printk("i2c-dev.o: i2c-%d lseek to %ld bytes relative to %d.\n",
-	       MINOR(inode->i_rdev),(long) offset,origin);
+	       minor(inode->i_rdev),(long) offset,origin);
 #endif /* DEBUG */
 	return -ESPIPE;
 }
@@ -165,7 +165,7 @@
 		return -ENOMEM;
 
 #ifdef DEBUG
-	printk("i2c-dev.o: i2c-%d reading %d bytes.\n",MINOR(inode->i_rdev),
+	printk("i2c-dev.o: i2c-%d reading %d bytes.\n",minor(inode->i_rdev),
 	       count);
 #endif
 
@@ -197,7 +197,7 @@
 	}
 
 #ifdef DEBUG
-	printk("i2c-dev.o: i2c-%d writing %d bytes.\n",MINOR(inode->i_rdev),
+	printk("i2c-dev.o: i2c-%d writing %d bytes.\n",minor(inode->i_rdev),
 	       count);
 #endif
 	ret = i2c_master_send(client,tmp,count);
@@ -218,7 +218,7 @@
 
 #ifdef DEBUG
 	printk("i2c-dev.o: i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n", 
-	       MINOR(inode->i_rdev),cmd, arg);
+	       minor(inode->i_rdev),cmd, arg);
 #endif /* DEBUG */
 
 	switch ( cmd ) {
diff --git a/drivers/i2c/i2c-proc.c b/drivers/i2c/i2c-proc.c
index 0145f77..9935044 100644
--- a/drivers/i2c/i2c-proc.c
+++ b/drivers/i2c/i2c-proc.c
@@ -119,6 +119,10 @@
 		sprintf(name_buffer, "%s-i2c-%d-%02x", prefix, id, addr);
 	}
 	*name = kmalloc(strlen(name_buffer) + 1, GFP_KERNEL);
+	if (!*name) {
+		printk (KERN_WARNING "i2c_create_name: not enough memory\n");
+		return -ENOMEM;
+	}
 	strcpy(*name, name_buffer);
 	return 0;
 }
diff --git a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c
index 1f4c535e..185d17e 100644
--- a/drivers/ide/aec62xx.c
+++ b/drivers/ide/aec62xx.c
@@ -220,7 +220,7 @@
 
 static int aec6210_tune_chipset (ide_drive_t *drive, byte speed)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 	int err			= 0;
 	unsigned short d_conf	= 0x0000;
@@ -256,10 +256,10 @@
 
 static int aec6260_tune_chipset (ide_drive_t *drive, byte speed)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 	byte unit		= (drive->select.b.unit & 0x01);
-	byte ultra_pci		= hwif->channel ? 0x45 : 0x44;
+	byte ultra_pci		= hwif->unit ? 0x45 : 0x44;
 	int err			= 0;
 	byte drive_conf		= 0x00;
 	byte ultra_conf		= 0x00;
@@ -293,7 +293,7 @@
 
 static int aec62xx_tune_chipset (ide_drive_t *drive, byte speed)
 {
-	if (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
+	if (drive->channel->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
 		return ((int) aec6210_tune_chipset(drive, speed));
 	} else {
 		return ((int) aec6260_tune_chipset(drive, speed));
@@ -304,7 +304,7 @@
 static int config_aec6210_chipset_for_dma (ide_drive_t *drive, byte ultra)
 {
 	struct hd_driveid *id	= drive->id;
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	byte unit		= (drive->select.b.unit & 0x01);
 	unsigned long dma_base	= hwif->dma_base;
 	byte speed		= -1;
@@ -349,7 +349,7 @@
 static int config_aec6260_chipset_for_dma (ide_drive_t *drive, byte ultra)
 {
 	struct hd_driveid *id	= drive->id;
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	byte unit		= (drive->select.b.unit & 0x01);
 	unsigned long dma_base	= hwif->dma_base;
 	byte speed		= -1;
@@ -396,7 +396,7 @@
 
 static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
 {
-	switch(HWIF(drive)->pci_dev->device) {	
+	switch(drive->channel->pci_dev->device) {
 		case PCI_DEVICE_ID_ARTOP_ATP850UF:
 			return config_aec6210_chipset_for_dma(drive, ultra);
 		case PCI_DEVICE_ID_ARTOP_ATP860:
@@ -418,7 +418,7 @@
 	else
 		speed = XFER_PIO_0 + min_t(byte, pio, 4);
 
-	switch(HWIF(drive)->pci_dev->device) {
+	switch(drive->channel->pci_dev->device) {
 		case PCI_DEVICE_ID_ARTOP_ATP850UF:
 			(void) aec6210_tune_chipset(drive, speed);
 		case PCI_DEVICE_ID_ARTOP_ATP860:
@@ -435,7 +435,7 @@
 	struct hd_driveid *id = drive->id;
 	ide_dma_action_t dma_func = ide_dma_on;
 
-	if (id && (id->capability & 1) && HWIF(drive)->autodma) {
+	if (id && (id->capability & 1) && drive->channel->autodma) {
 		/* Consult the list of known "bad" drives */
 		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
 			dma_func = ide_dma_off;
@@ -476,7 +476,7 @@
 no_dma_set:
 		aec62xx_tune_drive(drive, 5);
 	}
-	return HWIF(drive)->dmaproc(dma_func, drive);
+	return drive->channel->dmaproc(dma_func, drive);
 }
 
 /*
@@ -489,16 +489,16 @@
 			return config_drive_xfer_rate(drive);
 		case ide_dma_lostirq:
 		case ide_dma_timeout:
-			switch(HWIF(drive)->pci_dev->device) {
+			switch(drive->channel->pci_dev->device) {
 				case PCI_DEVICE_ID_ARTOP_ATP860:
 				case PCI_DEVICE_ID_ARTOP_ATP860R:
 //					{
 //						int i = 0;
 //						byte reg49h = 0;
-//						pci_read_config_byte(HWIF(drive)->pci_dev, 0x49, &reg49h);
+//						pci_read_config_byte(drive->channel->pci_dev, 0x49, &reg49h);
 //						for (i=0;i<256;i++)
-//							pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h|0x10);
-//						pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h & ~0x10);
+//							pci_write_config_byte(drive->channel->pci_dev, 0x49, reg49h|0x10);
+//						pci_write_config_byte(drive->channel->pci_dev, 0x49, reg49h & ~0x10);
 //					}
 //					return 0;
 				default:
@@ -530,16 +530,16 @@
 	return dev->irq;
 }
 
-unsigned int __init ata66_aec62xx (ide_hwif_t *hwif)
+unsigned int __init ata66_aec62xx(struct ata_channel *hwif)
 {
-	byte mask	= hwif->channel ? 0x02 : 0x01;
+	byte mask	= hwif->unit ? 0x02 : 0x01;
 	byte ata66	= 0;
 
 	pci_read_config_byte(hwif->pci_dev, 0x49, &ata66);
 	return ((ata66 & mask) ? 0 : 1);
 }
 
-void __init ide_init_aec62xx (ide_hwif_t *hwif)
+void __init ide_init_aec62xx(struct ata_channel *hwif)
 {
 #ifdef CONFIG_AEC62XX_TUNING
 	hwif->tuneproc = &aec62xx_tune_drive;
@@ -555,7 +555,7 @@
 #endif /* CONFIG_AEC62XX_TUNING */
 }
 
-void __init ide_dmacapable_aec62xx (ide_hwif_t *hwif, unsigned long dmabase)
+void __init ide_dmacapable_aec62xx(struct ata_channel *hwif, unsigned long dmabase)
 {
 #ifdef CONFIG_AEC62XX_TUNING
 	unsigned long flags;
@@ -565,7 +565,7 @@
 	__cli();		/* local CPU only */
 
 	pci_read_config_byte(hwif->pci_dev, 0x54, &reg54h);
-	pci_write_config_byte(hwif->pci_dev, 0x54, reg54h & ~(hwif->channel ? 0xF0 : 0x0F));
+	pci_write_config_byte(hwif->pci_dev, 0x54, reg54h & ~(hwif->unit ? 0xF0 : 0x0F));
 
 	__restore_flags(flags);	/* local CPU only */
 #endif /* CONFIG_AEC62XX_TUNING */
diff --git a/drivers/ide/ali14xx.c b/drivers/ide/ali14xx.c
index dd93eeb..10861d4 100644
--- a/drivers/ide/ali14xx.c
+++ b/drivers/ide/ali14xx.c
@@ -134,7 +134,7 @@
 		drive->name, pio - XFER_PIO_0, time1, time2, param1, param2, param3, param4);
 
 	/* stuff timing parameters into controller registers */
-	driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit;
+	driveNum = (drive->channel->index << 1) + drive->select.b.unit;
 	save_flags(flags);	/* all CPUs */
 	cli();			/* all CPUs */
 	outb_p(regOn, basePort);
@@ -214,7 +214,7 @@
 	ide_hwifs[1].tuneproc = &ali14xx_tune_drive;
 	ide_hwifs[0].mate = &ide_hwifs[1];
 	ide_hwifs[1].mate = &ide_hwifs[0];
-	ide_hwifs[1].channel = 1;
+	ide_hwifs[1].unit = 1;
 
 	/* initialize controller registers */
 	if (!initRegisters()) {
diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c
index a7a8fe6..b6a8e10 100644
--- a/drivers/ide/alim15x3.c
+++ b/drivers/ide/alim15x3.c
@@ -242,13 +242,13 @@
 static void ali15x3_tune_drive (ide_drive_t *drive, byte pio)
 {
 	struct ata_timing *t;
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev = hwif->pci_dev;
 	int s_time, a_time, c_time;
 	byte s_clc, a_clc, r_clc;
 	unsigned long flags;
-	int port = hwif->index ? 0x5c : 0x58;
-	int portFIFO = hwif->channel ? 0x55 : 0x54;
+	int port = hwif->unit ? 0x5c : 0x58;
+	int portFIFO = hwif->unit ? 0x55 : 0x54;
 	byte cd_dma_fifo = 0;
 
 	if (pio == 255)
@@ -305,11 +305,11 @@
 
 static int ali15x3_tune_chipset (ide_drive_t *drive, byte speed)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 	byte unit		= (drive->select.b.unit & 0x01);
 	byte tmpbyte		= 0x00;
-	int m5229_udma		= hwif->channel? 0x57 : 0x56;
+	int m5229_udma		= hwif->unit ? 0x57 : 0x56;
 	int err			= 0;
 
 	if (speed < XFER_UDMA_0) {
@@ -431,10 +431,10 @@
 
 static int ali15x3_config_drive_for_dma(ide_drive_t *drive)
 {
-	struct hd_driveid *id		= drive->id;
-	ide_hwif_t *hwif		= HWIF(drive);
-	ide_dma_action_t dma_func	= ide_dma_on;
-	byte can_ultra_dma		= ali15x3_can_ultra(drive);
+	struct hd_driveid *id = drive->id;
+	struct ata_channel *hwif = drive->channel;
+	ide_dma_action_t dma_func = ide_dma_on;
+	byte can_ultra_dma = ali15x3_can_ultra(drive);
 
 	if ((m5229_revision<=0x20) && (drive->type != ATA_DISK))
 		return hwif->dmaproc(ide_dma_off_quietly, drive);
@@ -537,7 +537,7 @@
  * of UDMA66 transfers. It doesn't check the drives.
  * But see note 2 below!
  */
-unsigned int __init ata66_ali15x3 (ide_hwif_t *hwif)
+unsigned int __init ata66_ali15x3(struct ata_channel *hwif)
 {
 	struct pci_dev *dev	= hwif->pci_dev;
 	unsigned int ata66	= 0;
@@ -597,7 +597,7 @@
 		/*
 		 * Allow ata66 if cable of current channel has 80 pins
 		 */
-		ata66 = (hwif->channel)?cable_80_pin[1]:cable_80_pin[0];
+		ata66 = (hwif->unit)?cable_80_pin[1]:cable_80_pin[0];
 	} else {
 		/*
 		 * revision 0x20 (1543-E, 1543-F)
@@ -632,14 +632,14 @@
 	return(ata66);
 }
 
-void __init ide_init_ali15x3 (ide_hwif_t *hwif)
+void __init ide_init_ali15x3(struct ata_channel *hwif)
 {
 #ifndef CONFIG_SPARC64
 	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;
+	hwif->irq = hwif->unit ? 15 : 14;
 
 	if (isa_dev) {
 		/*
@@ -651,14 +651,14 @@
 		ideic = ideic & 0x03;
 
 		/* get IRQ for IDE Controller */
-		if ((hwif->channel && ideic == 0x03) || (!hwif->channel && !ideic)) {
+		if ((hwif->unit && ideic == 0x03) || (!hwif->unit && !ideic)) {
 			/*
 			 * get SIRQ1 routing table
 			 */
 			pci_read_config_byte(isa_dev, 0x44, &inmir);
 			inmir = inmir & 0x0f;
 			hwif->irq = irq_routing_table[inmir];
-		} else if (hwif->channel && !(ideic & 0x01)) {
+		} else if (hwif->unit && !(ideic & 0x01)) {
 			/*
 			 * get SIRQ2 routing table
 			 */
@@ -690,7 +690,7 @@
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 }
 
-void __init ide_dmacapable_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase)
+void __init ide_dmacapable_ali15x3(struct ata_channel *hwif, unsigned long dmabase)
 {
 	if ((dmabase) && (m5229_revision < 0x20)) {
 		return;
diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c
index c1c036e..6c9e0ec 100644
--- a/drivers/ide/amd74xx.c
+++ b/drivers/ide/amd74xx.c
@@ -226,7 +226,7 @@
 
 static int amd_set_drive(ide_drive_t *drive, unsigned char speed)
 {
-	ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
+	ide_drive_t *peer = drive->channel->drives + (~drive->dn & 1);
 	struct ata_timing t, p;
 	int T, UT;
 
@@ -247,7 +247,7 @@
 
 	if (speed == XFER_UDMA_5 && amd_clock <= 33333) t.udma = 1;
 
-	amd_set_speed(HWIF(drive)->pci_dev, drive->dn, &t);
+	amd_set_speed(drive->channel->pci_dev, drive->dn, &t);
 
 	if (!drive->init_speed)	
 		drive->init_speed = speed;
@@ -263,7 +263,7 @@
 
 static void amd74xx_tune_drive(ide_drive_t *drive, unsigned char pio)
 {
-	if (!((amd_enabled >> HWIF(drive)->channel) & 1))
+	if (!((amd_enabled >> drive->channel->unit) & 1))
 		return;
 
 	if (pio == 255) {
@@ -287,7 +287,7 @@
 
 	if (func == ide_dma_check) {
 
-		short w80 = HWIF(drive)->udma_four;
+		short w80 = drive->channel->udma_four;
 
 		short speed = ata_timing_mode(drive,
 			XFER_PIO | XFER_EPIO | XFER_MWDMA | XFER_UDMA |
@@ -297,7 +297,7 @@
 
 		amd_set_drive(drive, speed);
 
-		func = (HWIF(drive)->autodma && (speed & XFER_MODE) != XFER_PIO)
+		func = (drive->channel->autodma && (speed & XFER_MODE) != XFER_PIO)
 			? ide_dma_on : ide_dma_off_quietly;
 	}
 
@@ -409,12 +409,12 @@
 	return 0;
 }
 
-unsigned int __init ata66_amd74xx(ide_hwif_t *hwif)
+unsigned int __init ata66_amd74xx(struct ata_channel *hwif)
 {
-	return ((amd_enabled & amd_80w) >> hwif->channel) & 1;
+	return ((amd_enabled & amd_80w) >> hwif->unit) & 1;
 }
 
-void __init ide_init_amd74xx(ide_hwif_t *hwif)
+void __init ide_init_amd74xx(struct ata_channel *hwif)
 {
 	int i;
 
@@ -426,7 +426,7 @@
 		hwif->drives[i].io_32bit = 1;
 		hwif->drives[i].unmask = 1;
 		hwif->drives[i].autotune = 1;
-		hwif->drives[i].dn = hwif->channel * 2 + i;
+		hwif->drives[i].dn = hwif->unit * 2 + i;
 	}
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
@@ -445,8 +445,8 @@
  * We allow the BM-DMA driver only work on enabled interfaces.
  */
 
-void __init ide_dmacapable_amd74xx(ide_hwif_t *hwif, unsigned long dmabase)
+void __init ide_dmacapable_amd74xx(struct ata_channel *hwif, unsigned long dmabase)
 {
-	if ((amd_enabled >> hwif->channel) & 1)
+	if ((amd_enabled >> hwif->unit) & 1)
 		ide_setup_dma(hwif, dmabase, 8);
 }
diff --git a/drivers/ide/buddha.c b/drivers/ide/buddha.c
index 404ddc0..b7881df 100644
--- a/drivers/ide/buddha.c
+++ b/drivers/ide/buddha.c
@@ -116,7 +116,7 @@
      *  Check and acknowledge the interrupt status
      */
 
-static int buddha_ack_intr(ide_hwif_t *hwif)
+static int buddha_ack_intr(struct ata_channel *hwif)
 {
     unsigned char ch;
 
@@ -126,7 +126,7 @@
     return 1;
 }
 
-static int xsurf_ack_intr(ide_hwif_t *hwif)
+static int xsurf_ack_intr(struct ata_channel *hwif)
 {
     unsigned char ch;
 
diff --git a/drivers/ide/cmd640.c b/drivers/ide/cmd640.c
index 27413c6..65aaf22 100644
--- a/drivers/ide/cmd640.c
+++ b/drivers/ide/cmd640.c
@@ -187,7 +187,7 @@
 /*
  * These are initialized to point at the devices we control
  */
-static ide_hwif_t  *cmd_hwif0, *cmd_hwif1;
+static struct ata_channel *cmd_hwif0, *cmd_hwif1;
 static ide_drive_t *cmd_drives[4];
 
 /*
@@ -429,7 +429,7 @@
 	cmd_hwif0 = &ide_hwifs[0]; /* default, if not found below */
 	cmd_hwif1 = &ide_hwifs[1]; /* default, if not found below */
 	for (i = 0; i < MAX_HWIFS; i++) {
-		ide_hwif_t *hwif = &ide_hwifs[i];
+		struct ata_channel *hwif = &ide_hwifs[i];
 		if (hwif->chipset == ide_unknown || hwif->chipset == ide_generic) {
 			if (hwif->io_ports[IDE_DATA_OFFSET] == 0x1f0)
 				cmd_hwif0 = hwif;
@@ -795,7 +795,7 @@
 		cmd_hwif1->chipset = ide_cmd640;
 		cmd_hwif0->mate = cmd_hwif1;
 		cmd_hwif1->mate = cmd_hwif0;
-		cmd_hwif1->channel = 1;
+		cmd_hwif1->unit = 1;
 #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
 		cmd_hwif1->tuneproc = &cmd640_tune_drive;
 #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c
index 39391d7..8f041da 100644
--- a/drivers/ide/cmd64x.c
+++ b/drivers/ide/cmd64x.c
@@ -211,7 +211,7 @@
 static void program_drive_counts (ide_drive_t *drive, int setup_count, int active_count, int recovery_count)
 {
 	unsigned long flags;
-	ide_drive_t *drives = HWIF(drive)->drives;
+	ide_drive_t *drives = drive->channel->drives;
 	byte temp_b;
 	static const byte setup_counts[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
 	static const byte recovery_counts[] =
@@ -224,7 +224,7 @@
 			{ DRWTIM0, DRWTIM1 },
 			{ DRWTIM2, DRWTIM3 }
 		};
-	int channel = (int) HWIF(drive)->channel;
+	int channel = drive->channel->unit;
 	int slave = (drives != drive);  /* Is this really the best way to determine this?? */
 
 	cmdprintk("program_drive_count parameters = s(%d),a(%d),r(%d),p(%d)\n", setup_count,
@@ -260,10 +260,10 @@
 	 * Program the address_setup clocks into ARTTIM reg,
 	 * and then the active/recovery counts into the DRWTIM reg
 	 */
-	(void) pci_read_config_byte(HWIF(drive)->pci_dev, arttim_regs[channel][slave], &temp_b);
-	(void) pci_write_config_byte(HWIF(drive)->pci_dev, arttim_regs[channel][slave],
+	(void) pci_read_config_byte(drive->channel->pci_dev, arttim_regs[channel][slave], &temp_b);
+	(void) pci_write_config_byte(drive->channel->pci_dev, arttim_regs[channel][slave],
 		((byte) setup_count) | (temp_b & 0x3f));
-	(void) pci_write_config_byte(HWIF(drive)->pci_dev, drwtim_regs[channel][slave],
+	(void) pci_write_config_byte(drive->channel->pci_dev, drwtim_regs[channel][slave],
 		(byte) ((active_count << 4) | recovery_count));
 	cmdprintk ("Write %x to %x\n", ((byte) setup_count) | (temp_b & 0x3f), arttim_regs[channel][slave]);
 	cmdprintk ("Write %x to %x\n", (byte) ((active_count << 4) | recovery_count), drwtim_regs[channel][slave]);
@@ -333,10 +333,10 @@
 		setup_count, active_count, recovery_count);
 }
 
-static byte cmd680_taskfile_timing (ide_hwif_t *hwif)
+static byte cmd680_taskfile_timing(struct ata_channel *hwif)
 {
 	struct pci_dev *dev	= hwif->pci_dev;
-	byte addr_mask		= (hwif->channel) ? 0xB2 : 0xA2;
+	byte addr_mask		= (hwif->unit) ? 0xB2 : 0xA2;
 	unsigned short		timing;
 
 	pci_read_config_word(dev, addr_mask, &timing);
@@ -353,7 +353,7 @@
 
 static void cmd680_tuneproc (ide_drive_t *drive, byte mode_wanted)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 	byte			drive_pci;
 	unsigned short		speedt;
@@ -394,10 +394,10 @@
 
 static void config_cmd680_chipset_for_pio (ide_drive_t *drive, byte set_speed)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 	u8 unit			= (drive->select.b.unit & 0x01);
-	u8 addr_mask		= (hwif->channel) ? 0x84 : 0x80;
+	u8 addr_mask		= (hwif->unit) ? 0x84 : 0x80;
 	u8 speed		= 0x00;
 	u8 mode_pci		= 0x00;
 	u8 channel_timings	= cmd680_taskfile_timing(hwif);
@@ -420,7 +420,7 @@
 
 static void config_chipset_for_pio (ide_drive_t *drive, byte set_speed)
 {
-        if (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_CMD_680) {
+        if (drive->channel->pci_dev->device == PCI_DEVICE_ID_CMD_680) {
 		config_cmd680_chipset_for_pio(drive, set_speed);
 	} else {
 		config_cmd64x_chipset_for_pio(drive, set_speed);
@@ -430,13 +430,13 @@
 static int cmd64x_tune_chipset (ide_drive_t *drive, byte speed)
 {
 #ifdef CONFIG_BLK_DEV_IDEDMA
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 	int err			= 0;
 
 	u8 unit			= (drive->select.b.unit & 0x01);
-	u8 pciU			= (hwif->channel) ? UDIDETCR1 : UDIDETCR0;
-	u8 pciD			= (hwif->channel) ? BMIDESR1 : BMIDESR0;
+	u8 pciU			= (hwif->unit) ? UDIDETCR1 : UDIDETCR0;
+	u8 pciD			= (hwif->unit) ? BMIDESR1 : BMIDESR0;
 	u8 regU			= 0;
 	u8 regD			= 0;
 
@@ -498,9 +498,9 @@
 
 static int cmd680_tune_chipset (ide_drive_t *drive, byte speed)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
-	u8 addr_mask		= (hwif->channel) ? 0x84 : 0x80;
+	u8 addr_mask		= (hwif->unit) ? 0x84 : 0x80;
 	u8 unit			= (drive->select.b.unit & 0x01);
 	u8 dma_pci		= 0;
 	u8 udma_pci		= 0;
@@ -615,7 +615,7 @@
 static int config_cmd64x_chipset_for_dma (ide_drive_t *drive, unsigned int rev, byte ultra_66)
 {
 	struct hd_driveid *id	= drive->id;
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 
 	byte speed		= 0x00;
@@ -741,7 +741,7 @@
 
 static int config_chipset_for_dma (ide_drive_t *drive, unsigned int rev, byte ultra_66)
 {
-	if (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_CMD_680)
+	if (drive->channel->pci_dev->device == PCI_DEVICE_ID_CMD_680)
 		return (config_cmd680_chipset_for_dma(drive));
 	return (config_cmd64x_chipset_for_dma(drive, rev, ultra_66));
 }
@@ -749,7 +749,7 @@
 static int cmd64x_config_drive_for_dma (ide_drive_t *drive)
 {
 	struct hd_driveid *id	= drive->id;
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 	unsigned int class_rev	= 0;
 	byte can_ultra_33	= 0;
@@ -822,7 +822,7 @@
 no_dma_set:
 		config_chipset_for_pio(drive, 1);
 	}
-	return HWIF(drive)->dmaproc(dma_func, drive);
+	return drive->channel->dmaproc(dma_func, drive);
 }
 
 static int cmd680_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
@@ -841,9 +841,9 @@
 {
 	byte dma_stat		= 0;
 	byte dma_alt_stat	= 0;
-	byte mask		= (HWIF(drive)->channel) ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0;
-	unsigned long dma_base	= HWIF(drive)->dma_base;
-	struct pci_dev *dev	= HWIF(drive)->pci_dev;
+	byte mask		= (drive->channel->unit) ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0;
+	unsigned long dma_base	= drive->channel->dma_base;
+	struct pci_dev *dev	= drive->channel->pci_dev;
 	byte jack_slap		= ((dev->device == PCI_DEVICE_ID_CMD_648) || (dev->device == PCI_DEVICE_ID_CMD_649)) ? 1 : 0;
 
 	switch (func) {
@@ -856,8 +856,8 @@
 			outb(dma_stat|6, dma_base+2);		/* clear the INTR & ERROR bits */
 			if (jack_slap) {
 				byte dma_intr	= 0;
-				byte dma_mask	= (HWIF(drive)->channel) ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0;
-				byte dma_reg	= (HWIF(drive)->channel) ? ARTTIM2 : CFR;
+				byte dma_mask	= (drive->channel->unit) ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0;
+				byte dma_reg	= (drive->channel->unit) ? ARTTIM2 : CFR;
 				(void) pci_read_config_byte(dev, dma_reg, &dma_intr);
 				/*
 				 * DAMN BMIDE is not connected to PCI space!
@@ -891,7 +891,7 @@
  */
 static int cmd646_1_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	unsigned long dma_base = hwif->dma_base;
 	byte dma_stat;
 
@@ -917,8 +917,8 @@
 static int cmd680_busproc (ide_drive_t * drive, int state)
 {
 #if 0
-	ide_hwif_t *hwif	= HWIF(drive);
-	u8 addr_mask		= (hwif->channel) ? 0xB0 : 0xA0;
+	struct ata_channel *hwif	= drive->channel;
+	u8 addr_mask		= (hwif->unit) ? 0xB0 : 0xA0;
 	u32 stat_config		= 0;
 
         pci_read_config_dword(hwif->pci_dev, addr_mask, &stat_config);
@@ -950,8 +950,8 @@
 static void cmd680_reset (ide_drive_t *drive)
 {
 #if 0
-	ide_hwif_t *hwif	= HWIF(drive);
-	u8 addr_mask		= (hwif->channel) ? 0xB0 : 0xA0;
+	struct ata_channel *hwif = drive->channel;
+	u8 addr_mask		= (hwif->unit) ? 0xB0 : 0xA0;
 	byte reset		= 0;
 
 	pci_read_config_byte(hwif->pci_dev, addr_mask, &reset);
@@ -1081,25 +1081,25 @@
 	return cmd64x_pci_init (dev);
 }
 
-unsigned int cmd680_ata66 (ide_hwif_t *hwif)
+unsigned int cmd680_ata66(struct ata_channel *hwif)
 {
 	byte ata66	= 0;
-	byte addr_mask	= (hwif->channel) ? 0xB0 : 0xA0;
+	byte addr_mask	= (hwif->unit) ? 0xB0 : 0xA0;
 
 	pci_read_config_byte(hwif->pci_dev, addr_mask, &ata66);
 	return (ata66 & 0x01) ? 1 : 0;
 }
 
-unsigned int cmd64x_ata66 (ide_hwif_t *hwif)
+unsigned int cmd64x_ata66(struct ata_channel *hwif)
 {
 	byte ata66 = 0;
-	byte mask = (hwif->channel) ? 0x02 : 0x01;
+	byte mask = (hwif->unit) ? 0x02 : 0x01;
 
 	pci_read_config_byte(hwif->pci_dev, BMIDECSR, &ata66);
 	return (ata66 & mask) ? 1 : 0;
 }
 
-unsigned int __init ata66_cmd64x (ide_hwif_t *hwif)
+unsigned int __init ata66_cmd64x(struct ata_channel *hwif)
 {
 	struct pci_dev *dev	= hwif->pci_dev;
 	if (dev->device == PCI_DEVICE_ID_CMD_680)
@@ -1107,7 +1107,7 @@
 	return cmd64x_ata66(hwif);
 }
 
-void __init ide_init_cmd64x (ide_hwif_t *hwif)
+void __init ide_init_cmd64x(struct ata_channel *hwif)
 {
 	struct pci_dev *dev	= hwif->pci_dev;
 	unsigned int class_rev;
diff --git a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c
index 23756d9..34526fa 100644
--- a/drivers/ide/cs5530.c
+++ b/drivers/ide/cs5530.c
@@ -101,7 +101,7 @@
  * After chip reset, the PIO timings are set to 0x0000e132, which is not valid.
  */
 #define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132)
-#define CS5530_BASEREG(hwif)	(((hwif)->dma_base & ~0xf) + ((hwif)->channel ? 0x30 : 0x20))
+#define CS5530_BASEREG(hwif)	(((hwif)->dma_base & ~0xf) + ((hwif)->unit ? 0x30 : 0x20))
 
 /*
  * cs5530_tuneproc() handles selection/setting of PIO modes
@@ -112,7 +112,7 @@
  */
 static void cs5530_tuneproc (ide_drive_t *drive, byte pio)	/* pio=255 means "autotune" */
 {
-	ide_hwif_t	*hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	unsigned int	format, basereg = CS5530_BASEREG(hwif);
 
 	if (pio == 255)
@@ -134,7 +134,7 @@
 static int cs5530_config_dma (ide_drive_t *drive)
 {
 	int			udma_ok = 1, mode = 0;
-	ide_hwif_t		*hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	int			unit = drive->select.b.unit;
 	ide_drive_t		*mate = &hwif->drives[unit^1];
 	struct hd_driveid	*id = drive->id;
@@ -344,7 +344,7 @@
  * This gets invoked by the IDE driver once for each channel,
  * and performs channel-specific pre-initialization before drive probing.
  */
-void __init ide_init_cs5530 (ide_hwif_t *hwif)
+void __init ide_init_cs5530(struct ata_channel *hwif)
 {
 	if (hwif->mate)
 		hwif->serialized = hwif->mate->serialized = 1;
diff --git a/drivers/ide/cy82c693.c b/drivers/ide/cy82c693.c
index 0634335..c4a17c0 100644
--- a/drivers/ide/cy82c693.c
+++ b/drivers/ide/cy82c693.c
@@ -192,7 +192,7 @@
 	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;
+        index = (drive->channel->unit == 0) ? CY82_INDEX_CHANNEL0 : CY82_INDEX_CHANNEL1;
 
 #if CY82C693_DEBUG_LOGS
        	/* for debug let's show the previous values */
@@ -200,7 +200,7 @@
 	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));
+	printk (KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n", drive->name, drive->channel->unit, drive->select.b.unit, (data&0x3), ((data>>2)&1));
 #endif /* CY82C693_DEBUG_LOGS */
 
 	data = (byte)mode|(byte)(single<<2);
@@ -209,7 +209,7 @@
 	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);
+	printk (KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n", drive->name, drive->channel->unit, drive->select.b.unit, mode, single);
 #endif /* CY82C693_DEBUG_INFO */
 
 	/* 
@@ -271,7 +271,7 @@
  */
 static void cy82c693_tune_drive (ide_drive_t *drive, byte pio)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev = hwif->pci_dev;
 	pio_clocks_t pclk;
 	unsigned int addrCtrl;
@@ -318,7 +318,7 @@
 		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);
+	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->unit, 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 */
@@ -371,7 +371,7 @@
 	}	
 
 #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);
+	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->unit, drive->select.b.unit, addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8);
 #endif /* CY82C693_DEBUG_INFO */
 }
 
@@ -431,7 +431,7 @@
 /*
  * the init function - called for each ide channel once
  */
-void __init ide_init_cy82c693(ide_hwif_t *hwif)
+void __init ide_init_cy82c693(struct ata_channel *hwif)
 {
 	hwif->chipset = ide_cy82c693;
 	hwif->tuneproc = cy82c693_tune_drive;
diff --git a/drivers/ide/dtc2278.c b/drivers/ide/dtc2278.c
index bc0aac0..b2cf501 100644
--- a/drivers/ide/dtc2278.c
+++ b/drivers/ide/dtc2278.c
@@ -89,7 +89,7 @@
 	 * 32bit I/O has to be enabled for *both* drives at the same time.
 	 */
 	drive->io_32bit = 1;
-	HWIF(drive)->drives[!drive->select.b.unit].io_32bit = 1;
+	drive->channel->drives[!drive->select.b.unit].io_32bit = 1;
 }
 
 void __init init_dtc2278 (void)
@@ -126,5 +126,5 @@
 	ide_hwifs[1].drives[1].no_unmask = 1;
 	ide_hwifs[0].mate = &ide_hwifs[1];
 	ide_hwifs[1].mate = &ide_hwifs[0];
-	ide_hwifs[1].channel = 1;
+	ide_hwifs[1].unit = 1;
 }
diff --git a/drivers/ide/gayle.c b/drivers/ide/gayle.c
index 5a5e8c04..543e38d 100644
--- a/drivers/ide/gayle.c
+++ b/drivers/ide/gayle.c
@@ -84,7 +84,7 @@
      *  Check and acknowledge the interrupt status
      */
 
-static int gayle_ack_intr_a4000(ide_hwif_t *hwif)
+static int gayle_ack_intr_a4000(struct ata_channel *hwif)
 {
     unsigned char ch;
 
@@ -94,7 +94,7 @@
     return 1;
 }
 
-static int gayle_ack_intr_a1200(ide_hwif_t *hwif)
+static int gayle_ack_intr_a1200(struct ata_channel *hwif)
 {
     unsigned char ch;
 
diff --git a/drivers/ide/hpt34x.c b/drivers/ide/hpt34x.c
index 2d0e82c..4e0e971 100644
--- a/drivers/ide/hpt34x.c
+++ b/drivers/ide/hpt34x.c
@@ -98,12 +98,12 @@
 	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->dn)) | (reg1 & ~(7 << (3*drive->dn))));
+	pci_read_config_dword(drive->channel->pci_dev, 0x44, &reg1);
+	pci_read_config_dword(drive->channel->pci_dev, 0x48, &reg2);
+	tmp1 = ((0x00 << (3 * drive->dn)) | (reg1 & ~(7 << (3 * drive->dn))));
 	tmp2 = (reg2 & ~(0x11 << drive->dn));
-	pci_write_config_dword(HWIF(drive)->pci_dev, 0x44, tmp1);
-	pci_write_config_dword(HWIF(drive)->pci_dev, 0x48, tmp2);
+	pci_write_config_dword(drive->channel->pci_dev, 0x44, tmp1);
+	pci_write_config_dword(drive->channel->pci_dev, 0x48, tmp2);
 }
 
 static int hpt34x_tune_chipset (ide_drive_t *drive, byte speed)
@@ -122,13 +122,13 @@
 		lo_speed >>= 5;
 	}
 
-	pci_read_config_dword(HWIF(drive)->pci_dev, 0x44, &reg1);
-	pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, &reg2);
+	pci_read_config_dword(drive->channel->pci_dev, 0x44, &reg1);
+	pci_read_config_dword(drive->channel->pci_dev, 0x48, &reg2);
 	tmp1 = ((lo_speed << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn))));
 	tmp2 = ((hi_speed << drive->dn) | reg2);
 	err = ide_config_drive_speed(drive, speed);
-	pci_write_config_dword(HWIF(drive)->pci_dev, 0x44, tmp1);
-	pci_write_config_dword(HWIF(drive)->pci_dev, 0x48, tmp2);
+	pci_write_config_dword(drive->channel->pci_dev, 0x44, tmp1);
+	pci_write_config_dword(drive->channel->pci_dev, 0x48, tmp2);
 
 	if (!drive->init_speed)
 		drive->init_speed = speed;
@@ -254,7 +254,7 @@
 	struct hd_driveid *id = drive->id;
 	ide_dma_action_t dma_func = ide_dma_on;
 
-	if (id && (id->capability & 1) && HWIF(drive)->autodma) {
+	if (id && (id->capability & 1) && drive->channel->autodma) {
 		/* Consult the list of known "bad" drives */
 		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
 			dma_func = ide_dma_off;
@@ -301,7 +301,7 @@
 		dma_func = ide_dma_off;
 #endif /* CONFIG_HPT34X_AUTODMA */
 
-	return HWIF(drive)->dmaproc(dma_func, drive);
+	return drive->channel->dmaproc(dma_func, drive);
 }
 
 /*
@@ -314,7 +314,7 @@
 
 int hpt34x_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	unsigned long dma_base = hwif->dma_base;
 	unsigned int count, reading = 0;
 	byte dma_stat;
@@ -334,6 +334,7 @@
 			drive->waiting_for_dma = 1;
 			if (drive->type != ATA_DISK)
 				return 0;
+			BUG_ON(HWGROUP(drive)->handler);
 			ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);	/* issue cmd to drive */
 			OUT_BYTE((reading == 9) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
 			return 0;
@@ -408,7 +409,7 @@
 	return dev->irq;
 }
 
-void __init ide_init_hpt34x (ide_hwif_t *hwif)
+void __init ide_init_hpt34x(struct ata_channel *hwif)
 {
 	hwif->tuneproc = &hpt34x_tune_drive;
 	hwif->speedproc = &hpt34x_tune_chipset;
diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
index 364d412..0703504 100644
--- a/drivers/ide/hpt366.c
+++ b/drivers/ide/hpt366.c
@@ -485,7 +485,7 @@
 static void hpt366_tune_chipset (ide_drive_t *drive, byte speed)
 {
 	byte regtime		= (drive->select.b.unit & 0x01) ? 0x44 : 0x40;
-	byte regfast		= (HWIF(drive)->channel) ? 0x55 : 0x51;
+	byte regfast		= (drive->channel->unit) ? 0x55 : 0x51;
 			/*
 			 * since the channel is always 0 it does not matter.
 			 */
@@ -497,11 +497,11 @@
 	/*
 	 * Disable the "fast interrupt" prediction. 
 	 */
-	pci_read_config_byte(HWIF(drive)->pci_dev, regfast, &drive_fast);
+	pci_read_config_byte(drive->channel->pci_dev, regfast, &drive_fast);
 	if (drive_fast & 0x02)
-		pci_write_config_byte(HWIF(drive)->pci_dev, regfast, drive_fast & ~0x20);
+		pci_write_config_byte(drive->channel->pci_dev, regfast, drive_fast & ~0x20);
 
-	pci_read_config_dword(HWIF(drive)->pci_dev, regtime, &reg1);
+	pci_read_config_dword(drive->channel->pci_dev, regtime, &reg1);
 	/* detect bus speed by looking at control reg timing: */
 	switch((reg1 >> 8) & 7) {
 		case 5:
@@ -531,18 +531,18 @@
 	}	
 	reg2 &= ~0x80000000;
 
-	pci_write_config_dword(HWIF(drive)->pci_dev, regtime, reg2);
+	pci_write_config_dword(drive->channel->pci_dev, regtime, reg2);
 }
 
 static void hpt370_tune_chipset (ide_drive_t *drive, byte speed)
 {
-	byte regfast		= (HWIF(drive)->channel) ? 0x55 : 0x51;
+	byte regfast		= (drive->channel->unit) ? 0x55 : 0x51;
 	unsigned int list_conf	= 0;
 	unsigned int drive_conf = 0;
 	unsigned int conf_mask	= (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000;
 	byte drive_pci		= 0x40 + (drive->dn * 4);
 	byte new_fast, drive_fast		= 0;
-	struct pci_dev *dev 	= HWIF(drive)->pci_dev;
+	struct pci_dev *dev	= drive->channel->pci_dev;
 
 	/*
 	 * Disable the "fast interrupt" prediction.
@@ -561,7 +561,7 @@
 		new_fast |= 0x01;
 #endif
 	if (new_fast != drive_fast)
-		pci_write_config_byte(HWIF(drive)->pci_dev, regfast, new_fast);
+		pci_write_config_byte(drive->channel->pci_dev, regfast, new_fast);
 
 	list_conf = pci_bus_clock_list(speed, 
 				       (struct chipset_bus_clock_list_entry *)
@@ -585,7 +585,7 @@
 	if (!drive->init_speed)
 		drive->init_speed = speed;
 
-	if (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) {
+	if (pci_rev_check_hpt3xx(drive->channel->pci_dev)) {
 		hpt370_tune_chipset(drive, speed);
         } else {
                 hpt366_tune_chipset(drive, speed);
@@ -670,7 +670,7 @@
 	if ((id->dma_ultra & 0x0020) &&
 	    (!check_in_drive_lists(drive, bad_ata100_5)) &&
 	    (HPT370_ALLOW_ATA100_5) &&
-	    (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) &&
+	    (pci_rev_check_hpt3xx(drive->channel->pci_dev)) &&
 	    (ultra66)) {
 		speed = XFER_UDMA_5;
 	} else if ((id->dma_ultra & 0x0010) &&
@@ -720,23 +720,23 @@
 	if (drive->quirk_list) {
 		/* drives in the quirk_list may not like intr setups/cleanups */
 	} else {
-		OUT_BYTE((drive)->ctl|2, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]);
+		OUT_BYTE((drive)->ctl|2, drive->channel->io_ports[IDE_CONTROL_OFFSET]);
 	}
 }
 
 void hpt3xx_maskproc (ide_drive_t *drive, int mask)
 {
 	if (drive->quirk_list) {
-		if (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) {
+		if (pci_rev_check_hpt3xx(drive->channel->pci_dev)) {
 			byte reg5a = 0;
-			pci_read_config_byte(HWIF(drive)->pci_dev, 0x5a, &reg5a);
+			pci_read_config_byte(drive->channel->pci_dev, 0x5a, &reg5a);
 			if (((reg5a & 0x10) >> 4) != mask)
-				pci_write_config_byte(HWIF(drive)->pci_dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10));
+				pci_write_config_byte(drive->channel->pci_dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10));
 		} else {
 			if (mask) {
-				disable_irq(HWIF(drive)->irq);
+				disable_irq(drive->channel->irq);
 			} else {
-				enable_irq(HWIF(drive)->irq);
+				enable_irq(drive->channel->irq);
 			}
 		}
 	} else {
@@ -750,7 +750,7 @@
 	struct hd_driveid *id = drive->id;
 	ide_dma_action_t dma_func = ide_dma_on;
 
-	if (id && (id->capability & 1) && HWIF(drive)->autodma) {
+	if (id && (id->capability & 1) && drive->channel->autodma) {
 		/* Consult the list of known "bad" drives */
 		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
 			dma_func = ide_dma_off;
@@ -791,7 +791,7 @@
 
 		config_chipset_for_pio(drive);
 	}
-	return HWIF(drive)->dmaproc(dma_func, drive);
+	return drive->channel->dmaproc(dma_func, drive);
 }
 
 /*
@@ -803,7 +803,7 @@
 int hpt366_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
 {
 	byte reg50h = 0, reg52h = 0, reg5ah = 0, dma_stat = 0;
-	unsigned long dma_base = HWIF(drive)->dma_base;
+	unsigned long dma_base = drive->channel->dma_base;
 
 	switch (func) {
 		case ide_dma_check:
@@ -812,21 +812,21 @@
 			dma_stat = inb(dma_base+2);
 			return (dma_stat & 4) == 4;	/* return 1 if INTR asserted */
 		case ide_dma_lostirq:
-			pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, &reg50h);
-			pci_read_config_byte(HWIF(drive)->pci_dev, 0x52, &reg52h);
-			pci_read_config_byte(HWIF(drive)->pci_dev, 0x5a, &reg5ah);
+			pci_read_config_byte(drive->channel->pci_dev, 0x50, &reg50h);
+			pci_read_config_byte(drive->channel->pci_dev, 0x52, &reg52h);
+			pci_read_config_byte(drive->channel->pci_dev, 0x5a, &reg5ah);
 			printk("%s: (%s)  reg50h=0x%02x, reg52h=0x%02x, reg5ah=0x%02x\n",
 				drive->name,
 				ide_dmafunc_verbose(func),
 				reg50h, reg52h, reg5ah);
 			if (reg5ah & 0x10)
-				pci_write_config_byte(HWIF(drive)->pci_dev, 0x5a, reg5ah & ~0x10);
+				pci_write_config_byte(drive->channel->pci_dev, 0x5a, reg5ah & ~0x10);
 			/* fall through to a reset */
 #if 0
 		case ide_dma_begin:
 		case ide_dma_end:
 			/* reset the chips state over and over.. */
-			pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, 0x13);
+			pci_write_config_byte(drive->channel->pci_dev, 0x51, 0x13);
 #endif
 			break;
 		case ide_dma_timeout:
@@ -838,10 +838,10 @@
 
 int hpt370_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	unsigned long dma_base = hwif->dma_base;
-	byte regstate = hwif->channel ? 0x54 : 0x50;
-	byte reginfo = hwif->channel ? 0x56 : 0x52;
+	byte regstate = hwif->unit ? 0x54 : 0x50;
+	byte reginfo = hwif->unit ? 0x56 : 0x52;
 	byte dma_stat;
 
 	switch (func) {
@@ -899,23 +899,23 @@
 void hpt3xx_reset (ide_drive_t *drive)
 {
 #if 0
-	unsigned long high_16	= pci_resource_start(HWIF(drive)->pci_dev, 4);
-	byte reset		= (HWIF(drive)->channel) ? 0x80 : 0x40;
+	unsigned long high_16	= pci_resource_start(drive->channel->pci_dev, 4);
+	byte reset		= (drive->channel->unit) ? 0x80 : 0x40;
 	byte reg59h		= 0;
 
-	pci_read_config_byte(HWIF(drive)->pci_dev, 0x59, &reg59h);
-	pci_write_config_byte(HWIF(drive)->pci_dev, 0x59, reg59h|reset);
-	pci_write_config_byte(HWIF(drive)->pci_dev, 0x59, reg59h);
+	pci_read_config_byte(drive->channel->pci_dev, 0x59, &reg59h);
+	pci_write_config_byte(drive->channel->pci_dev, 0x59, reg59h|reset);
+	pci_write_config_byte(drive->channel->pci_dev, 0x59, reg59h);
 #endif
 }
 
 #if 0
 static int hpt3xx_tristate (ide_drive_t * drive, int state)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif	= drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
-	byte reset		= (hwif->channel) ? 0x80 : 0x40;
-	byte state_reg		= (hwif->channel) ? 0x57 : 0x53;
+	byte reset		= (hwif->unit) ? 0x80 : 0x40;
+	byte state_reg		= (hwif->unit) ? 0x57 : 0x53;
 	byte reg59h		= 0;
 	byte regXXh		= 0;
 
@@ -951,7 +951,7 @@
 #define TRISTATE_BIT  0x8000
 static int hpt370_busproc(ide_drive_t * drive, int state)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	byte tristate, resetmask, bus_reg;
 	u16 tri_reg;
 
@@ -960,7 +960,7 @@
 
 	hwif->bus_state = state;
 
-	if (hwif->channel) { 
+	if (hwif->unit) { 
 		/* secondary channel */
 		tristate = 0x56;
 		resetmask = 0x80; 
@@ -1136,10 +1136,10 @@
 	return dev->irq;
 }
 
-unsigned int __init ata66_hpt366 (ide_hwif_t *hwif)
+unsigned int __init ata66_hpt366(struct ata_channel *hwif)
 {
 	byte ata66	= 0;
-	byte regmask	= (hwif->channel) ? 0x01 : 0x02;
+	byte regmask	= (hwif->unit) ? 0x01 : 0x02;
 
 	pci_read_config_byte(hwif->pci_dev, 0x5a, &ata66);
 #ifdef DEBUG
@@ -1150,7 +1150,7 @@
 	return ((ata66 & regmask) ? 0 : 1);
 }
 
-void __init ide_init_hpt366 (ide_hwif_t *hwif)
+void __init ide_init_hpt366(struct ata_channel *hwif)
 {
 	int hpt_rev;
 
@@ -1210,12 +1210,12 @@
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 }
 
-void __init ide_dmacapable_hpt366 (ide_hwif_t *hwif, unsigned long dmabase)
+void __init ide_dmacapable_hpt366(struct ata_channel *hwif, unsigned long dmabase)
 {
 	byte masterdma = 0, slavedma = 0;
 	byte dma_new = 0, dma_old = inb(dmabase+2);
-	byte primary	= hwif->channel ? 0x4b : 0x43;
-	byte secondary	= hwif->channel ? 0x4f : 0x47;
+	byte primary	= hwif->unit ? 0x4b : 0x43;
+	byte secondary	= hwif->unit ? 0x4f : 0x47;
 	unsigned long flags;
 
 	__save_flags(flags);	/* local CPU only */
diff --git a/drivers/ide/ht6560b.c b/drivers/ide/ht6560b.c
index 7a71ef1..4212382 100644
--- a/drivers/ide/ht6560b.c
+++ b/drivers/ide/ht6560b.c
@@ -321,7 +321,7 @@
 			ide_hwifs[1].serialized = 1;  /* is this needed? */
 			ide_hwifs[0].mate = &ide_hwifs[1];
 			ide_hwifs[1].mate = &ide_hwifs[0];
-			ide_hwifs[1].channel = 1;
+			ide_hwifs[1].unit = 1;
 			
 			/*
 			 * Setting default configurations for drives
diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c
index 70cb1be..4b73826 100644
--- a/drivers/ide/icside.c
+++ b/drivers/ide/icside.c
@@ -224,7 +224,7 @@
 #define NR_ENTRIES 256
 #define TABLE_SIZE (NR_ENTRIES * 8)
 
-static int ide_build_sglist(ide_hwif_t *hwif, struct request *rq)
+static int ide_build_sglist(struct ata_channel *hwif, struct request *rq)
 {
 	request_queue_t *q = &hwif->drives[DEVICE_NR(rq->rq_dev) & 1].queue;
 	struct scatterlist *sg = hwif->sg_table;
@@ -245,16 +245,16 @@
 static int
 icside_build_dmatable(ide_drive_t *drive, int reading)
 {
-	return HWIF(drive)->sg_nents = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq);
+	return drive->channel->sg_nents = ide_build_sglist(drive->channel, HWGROUP(drive)->rq);
 }
 
 /* Teardown mappings after DMA has completed.  */
 static void icside_destroy_dmatable(ide_drive_t *drive)
 {
-	struct scatterlist *sg = HWIF(drive)->sg_table;
-	int nents = HWIF(drive)->sg_nents;
+	struct scatterlist *sg = drive->channel->sg_table;
+	int nents = drive->channel->sg_nents;
 
-	pci_unmap_sg(NULL, sg, nents, HWIF(drive)->sg_dma_direction);
+	pci_unmap_sg(NULL, sg, nents, drive->channel->sg_dma_direction);
 }
 
 /*
@@ -333,7 +333,7 @@
 	int i;
 	byte stat, dma_stat;
 
-	dma_stat = HWIF(drive)->dmaproc(ide_dma_end, drive);
+	dma_stat = drive->channel->dmaproc(ide_dma_end, drive);
 	stat = GET_STAT();			/* get drive status */
 	if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
 		if (!dma_stat) {
@@ -356,7 +356,7 @@
 icside_dma_check(ide_drive_t *drive)
 {
 	struct hd_driveid *id = drive->id;
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	int autodma = hwif->autodma;
 	int xfer_mode = XFER_PIO_2;
 	int func = ide_dma_off_quietly;
@@ -397,7 +397,7 @@
 static int
 icside_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	int count, reading = 0;
 
 	switch (func) {
@@ -436,14 +436,15 @@
 		 */
 		set_dma_speed(hwif->hw.dma, drive->drive_data);
 
-		set_dma_sg(hwif->hw.dma, HWIF(drive)->sg_table, count);
+		set_dma_sg(hwif->hw.dma, drive->channel->sg_table, count);
 		set_dma_mode(hwif->hw.dma, reading ? DMA_MODE_READ
 			     : DMA_MODE_WRITE);
 
 		drive->waiting_for_dma = 1;
-		if (drive->media != ide_disk)
+		if (drive->type != ATA_DISK)
 			return 0;
 
+		BUG_ON(HWGROUP(drive)->handler);
 		ide_set_handler(drive, &icside_dmaintr, WAIT_CMD, NULL);
 		OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA,
 			 IDE_COMMAND_REG);
@@ -473,7 +474,7 @@
 }
 
 static int
-icside_setup_dma(ide_hwif_t *hwif, int autodma)
+icside_setup_dma(struct ata_channel *hwif, int autodma)
 {
 	printk("    %s: SG-DMA", hwif->name);
 
@@ -498,7 +499,7 @@
 	return 0;
 }
 
-void ide_release_dma(ide_hwif_t *hwif)
+void ide_release_dma(struct ata_channel *hwif)
 {
 	if (hwif->sg_table) {
 		kfree(hwif->sg_table);
@@ -507,10 +508,10 @@
 }
 #endif
 
-static ide_hwif_t *
+static struct ata_channel *
 icside_find_hwif(unsigned long dataport)
 {
-	ide_hwif_t *hwif;
+	struct ata_channel *hwif;
 	int index;
 
 	for (index = 0; index < MAX_HWIFS; ++index) {
@@ -530,11 +531,11 @@
 	return hwif;
 }
 
-static ide_hwif_t *
+static struct ata_channel *
 icside_setup(unsigned long base, struct cardinfo *info, int irq)
 {
 	unsigned long port = base + info->dataoffset;
-	ide_hwif_t *hwif;
+	struct ata_channel *hwif;
 
 	hwif = icside_find_hwif(base);
 	if (hwif) {
@@ -562,7 +563,7 @@
 static int __init icside_register_v5(struct expansion_card *ec, int autodma)
 {
 	unsigned long slot_port;
-	ide_hwif_t *hwif;
+	struct ata_channel *hwif;
 
 	slot_port = ecard_address(ec, ECARD_MEMC, 0);
 
@@ -584,7 +585,8 @@
 static int __init icside_register_v6(struct expansion_card *ec, int autodma)
 {
 	unsigned long slot_port, port;
-	ide_hwif_t *hwif, *mate;
+	struct ata_channel *hwif;
+	struct ata_channel *mate;
 	int sel = 0;
 
 	slot_port = ecard_address(ec, ECARD_IOC, ECARD_FAST);
@@ -620,7 +622,7 @@
 			hwif->hw.dma  = ec->dma;
 			hwif->hw.priv = (void *)
 					(port + ICS_ARCIN_V6_INTRSTAT_1);
-			hwif->channel = 0;
+			hwif->unit = 0;
 			icside_setup_dma(hwif, autodma);
 		}
 		if (mate) {
@@ -629,7 +631,7 @@
 			mate->hw.dma  = ec->dma;
 			mate->hw.priv = (void *)
 					(port + ICS_ARCIN_V6_INTRSTAT_2);
-			mate->channel = 1;
+			mate->unit = 1;
 			icside_setup_dma(mate, autodma);
 		}
 	}
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index c0b2d70..e5ab895 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -723,9 +723,9 @@
 
 	if (info->dma) {
 		if (info->cmd == READ) {
-			info->dma = !HWIF(drive)->dmaproc(ide_dma_read, drive);
+			info->dma = !drive->channel->dmaproc(ide_dma_read, drive);
 		} else if (info->cmd == WRITE) {
-			info->dma = !HWIF(drive)->dmaproc(ide_dma_write, drive);
+			info->dma = !drive->channel->dmaproc(ide_dma_write, drive);
 		} else {
 			printk("ide-cd: DMA set, but not allowed\n");
 		}
@@ -740,11 +740,12 @@
 	OUT_BYTE (xferlen >> 8  , IDE_HCYL_REG);
 	if (IDE_CONTROL_REG)
 		OUT_BYTE (drive->ctl, IDE_CONTROL_REG);
- 
+
 	if (info->dma)
-		(void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
+		(void) drive->channel->dmaproc(ide_dma_begin, drive);
 
 	if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
+		BUG_ON(HWGROUP(drive)->handler);
 		ide_set_handler (drive, handler, WAIT_CMD, cdrom_timer_expiry);
 		OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */
 		return ide_started;
@@ -787,6 +788,7 @@
 	}
 
 	/* Arm the interrupt handler. */
+	BUG_ON(HWGROUP(drive)->handler);
 	ide_set_handler (drive, handler, timeout, cdrom_timer_expiry);
 
 	/* Send the command to the device. */
@@ -899,8 +901,8 @@
 	/* Check for errors. */
 	if (dma) {
 		info->dma = 0;
-		if ((dma_error = HWIF(drive)->dmaproc(ide_dma_end, drive)))
-			HWIF(drive)->dmaproc(ide_dma_off, drive);
+		if ((dma_error = drive->channel->dmaproc(ide_dma_end, drive)))
+			drive->channel->dmaproc(ide_dma_off, drive);
 	}
 
 	if (cdrom_decode_status (&startstop, drive, 0, &stat))
@@ -1005,7 +1007,9 @@
 
 	/* Done moving data!
 	   Wait for another interrupt. */
+	BUG_ON(HWGROUP(drive)->handler);
 	ide_set_handler(drive, &cdrom_read_intr, WAIT_CMD, NULL);
+
 	return ide_started;
 }
 
@@ -1335,6 +1339,8 @@
 	}
 
 	/* Now we wait for another interrupt. */
+
+	BUG_ON(HWGROUP(drive)->handler);
 	ide_set_handler (drive, &cdrom_pc_intr, WAIT_CMD, cdrom_timer_expiry);
 	return ide_started;
 }
@@ -1476,9 +1482,9 @@
 	/* Check for errors. */
 	if (dma) {
 		info->dma = 0;
-		if ((dma_error = HWIF(drive)->dmaproc(ide_dma_end, drive))) {
+		if ((dma_error = drive->channel->dmaproc(ide_dma_end, drive))) {
 			printk("ide-cd: write dma error\n");
-			HWIF(drive)->dmaproc(ide_dma_off, drive);
+			drive->channel->dmaproc(ide_dma_off, drive);
 		}
 	}
 
@@ -1559,6 +1565,7 @@
 	}
 
 	/* re-arm handler */
+	BUG_ON(HWGROUP(drive)->handler);
 	ide_set_handler(drive, &cdrom_write_intr, 5 * WAIT_CMD, NULL);
 	return ide_started;
 }
@@ -2021,14 +2028,14 @@
 
 	/* Now try to get the total cdrom capacity. */
 	minor = (drive->select.b.unit) << PARTN_BITS;
-	dev = mk_kdev(HWIF(drive)->major, minor);
+	dev = mk_kdev(drive->channel->major, minor);
 	stat = cdrom_get_last_written(dev, &toc->capacity);
 	if (stat)
 		stat = cdrom_read_capacity(drive, &toc->capacity, sense);
 	if (stat)
 		toc->capacity = 0x1fffff;
 
-	HWIF(drive)->gd->sizes[drive->select.b.unit << PARTN_BITS] = (toc->capacity * SECTORS_PER_FRAME) >> (BLOCK_SIZE_BITS - 9);
+	drive->channel->gd->sizes[drive->select.b.unit << PARTN_BITS] = (toc->capacity * SECTORS_PER_FRAME) >> (BLOCK_SIZE_BITS - 9);
 	drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
 
 	/* Remember that we've read this stuff. */
@@ -2487,7 +2494,7 @@
 	struct cdrom_device_info *devinfo = &info->devinfo;
 	int minor = (drive->select.b.unit) << PARTN_BITS;
 
-	devinfo->dev = mk_kdev(HWIF(drive)->major, minor);
+	devinfo->dev = mk_kdev(drive->channel->major, minor);
 	devinfo->ops = &ide_cdrom_dops;
 	devinfo->mask = 0;
 	*(int *)&devinfo->speed = CDROM_STATE_FLAGS (drive)->current_speed;
@@ -2519,7 +2526,7 @@
 	 */
 
 	devinfo->de = devfs_register(drive->de, "cd", DEVFS_FL_DEFAULT,
-				     HWIF(drive)->major, minor,
+				     drive->channel->major, minor,
 				     S_IFBLK | S_IRUGO | S_IWUGO,
 				     ide_fops, NULL);
 
@@ -2661,7 +2668,7 @@
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (drive->using_dma)
-		(void) HWIF(drive)->dmaproc(ide_dma_verbose, drive);
+		(void) drive->channel->dmaproc(ide_dma_verbose, drive);
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 	printk("\n");
 
@@ -2684,8 +2691,8 @@
 	/*
 	 * default to read-only always and fix latter at the bottom
 	 */
-	set_device_ro(mk_kdev(HWIF(drive)->major, minor), 1);
-	set_blocksize(mk_kdev(HWIF(drive)->major, minor), CD_FRAMESIZE);
+	set_device_ro(mk_kdev(drive->channel->major, minor), 1);
+	set_blocksize(mk_kdev(drive->channel->major, minor), CD_FRAMESIZE);
 	blk_queue_hardsect_size(&drive->queue, CD_FRAMESIZE);
 
 	blk_queue_prep_rq(&drive->queue, ll_10byte_cmd_build);
@@ -2807,7 +2814,7 @@
 	nslots = ide_cdrom_probe_capabilities (drive);
 
 	if (CDROM_CONFIG_FLAGS(drive)->dvd_ram)
-		set_device_ro(mk_kdev(HWIF(drive)->major, minor), 0);
+		set_device_ro(mk_kdev(drive->channel->major, minor), 0);
 
 	if (ide_cdrom_register (drive, nslots)) {
 		printk ("%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
@@ -2854,7 +2861,7 @@
 static
 int ide_cdrom_check_media_change (ide_drive_t *drive)
 {
-	return cdrom_media_changed(mk_kdev (HWIF (drive)->major,
+	return cdrom_media_changed(mk_kdev (drive->channel->major,
 			(drive->select.b.unit) << PARTN_BITS));
 }
 
@@ -2875,14 +2882,14 @@
 
 	/* for general /dev/cdrom like mounting, one big disc */
 	drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
-	HWIF(drive)->gd->sizes[minor] = toc->capacity * BLOCKS_PER_FRAME;
+	drive->channel->gd->sizes[minor] = toc->capacity * BLOCKS_PER_FRAME;
 
 	/*
 	 * reset block size, ide_revalidate_disk incorrectly sets it to
 	 * 1024 even for CDROM's
 	 */
-	blk_size[HWIF(drive)->major] = HWIF(drive)->gd->sizes;
-	set_blocksize(mk_kdev(HWIF(drive)->major, minor), CD_FRAMESIZE);
+	blk_size[drive->channel->major] = drive->channel->gd->sizes;
+	set_blocksize(mk_kdev(drive->channel->major, minor), CD_FRAMESIZE);
 }
 
 static
@@ -2984,15 +2991,14 @@
 		memset (info, 0, sizeof (struct cdrom_info));
 		drive->driver_data = info;
 
-		/* ATA-PATTERN */
-		ata_ops(drive)->busy++;
+		MOD_INC_USE_COUNT;
 		if (ide_cdrom_setup (drive)) {
-			ata_ops(drive)->busy--;
+			MOD_DEC_USE_COUNT;
 			if (ide_cdrom_cleanup (drive))
 				printk ("%s: ide_cdrom_cleanup failed in ide_cdrom_init\n", drive->name);
 			continue;
 		}
-		ata_ops(drive)->busy--;
+		MOD_DEC_USE_COUNT;
 
 		failed--;
 	}
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 5f59835..7a72138 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -51,7 +51,7 @@
 #include <asm/io.h>
 
 #ifdef CONFIG_BLK_DEV_PDC4030
-#define IS_PDC4030_DRIVE (HWIF(drive)->chipset == ide_pdc4030)
+#define IS_PDC4030_DRIVE (drive->channel->chipset == ide_pdc4030)
 #else
 #define IS_PDC4030_DRIVE (0)	/* auto-NULLs out pdc4030 code */
 #endif
@@ -106,9 +106,209 @@
 	return 0;	/* lba_capacity value may be bad */
 }
 
-static ide_startstop_t chs_do_request(ide_drive_t *drive, struct request *rq, unsigned long block);
-static ide_startstop_t lba28_do_request(ide_drive_t *drive, struct request *rq, unsigned long block);
-static ide_startstop_t lba48_do_request(ide_drive_t *drive, struct request *rq, unsigned long long block);
+static u8 get_command(ide_drive_t *drive, int cmd)
+{
+	int lba48bit = (drive->id->cfs_enable_2 & 0x0400) ? 1 : 0;
+
+#if 1
+	lba48bit = drive->addressing;
+#endif
+
+	if (lba48bit) {
+		if (cmd == READ) {
+			if (drive->using_dma)
+				return WIN_READDMA_EXT;
+			else if (drive->mult_count)
+				return WIN_MULTREAD_EXT;
+			else
+				return WIN_READ_EXT;
+		} else if (cmd == WRITE) {
+			if (drive->using_dma)
+				return WIN_WRITEDMA_EXT;
+			else if (drive->mult_count)
+				return WIN_MULTWRITE_EXT;
+			else
+				return WIN_WRITE_EXT;
+		}
+	} else {
+		if (cmd == READ) {
+			if (drive->using_dma)
+				return WIN_READDMA;
+			else if (drive->mult_count)
+				return WIN_MULTREAD;
+			else
+				return WIN_READ;
+		} else if (cmd == WRITE) {
+			if (drive->using_dma)
+				return WIN_WRITEDMA;
+			else if (drive->mult_count)
+				return WIN_MULTWRITE;
+			else
+				return WIN_WRITE;
+		}
+	}
+	return WIN_NOP;
+}
+
+static ide_startstop_t chs_do_request(ide_drive_t *drive, struct request *rq, unsigned long block)
+{
+	struct hd_drive_task_hdr	taskfile;
+	struct hd_drive_hob_hdr		hobfile;
+	ide_task_t			args;
+	int				sectors;
+
+	unsigned int track	= (block / drive->sect);
+	unsigned int sect	= (block % drive->sect) + 1;
+	unsigned int head	= (track % drive->head);
+	unsigned int cyl	= (track / drive->head);
+
+	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
+	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
+
+	sectors = rq->nr_sectors;
+	if (sectors == 256)
+		sectors = 0;
+
+	taskfile.sector_count	= sectors;
+
+	taskfile.sector_number	= sect;
+	taskfile.low_cylinder	= cyl;
+	taskfile.high_cylinder	= (cyl>>8);
+
+	taskfile.device_head	= head;
+	taskfile.device_head	|= drive->select.all;
+	taskfile.command	=  get_command(drive, rq_data_dir(rq));
+
+#ifdef DEBUG
+	printk("%s: %sing: ", drive->name,
+		(rq_data_dir(rq)==READ) ? "read" : "writ");
+	if (lba)	printk("LBAsect=%lld, ", block);
+	else		printk("CHS=%d/%d/%d, ", cyl, head, sect);
+	printk("sectors=%ld, ", rq->nr_sectors);
+	printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);
+#endif
+
+	args.taskfile = taskfile;
+	args.hobfile = hobfile;
+	ide_cmd_type_parser(&args);
+	rq->special = &args;
+
+	return ata_taskfile(drive,
+			&args.taskfile,
+			&args.hobfile,
+			args.handler,
+			args.prehandler,
+			rq);
+}
+
+static ide_startstop_t lba28_do_request(ide_drive_t *drive, struct request *rq, unsigned long block)
+{
+	struct hd_drive_task_hdr	taskfile;
+	struct hd_drive_hob_hdr		hobfile;
+	ide_task_t			args;
+	int				sectors;
+
+	sectors = rq->nr_sectors;
+	if (sectors == 256)
+		sectors = 0;
+
+	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
+	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
+
+	taskfile.sector_count	= sectors;
+	taskfile.sector_number	= block;
+	taskfile.low_cylinder	= (block >>= 8);
+
+	taskfile.high_cylinder	= (block >>= 8);
+
+	taskfile.device_head	= ((block >> 8) & 0x0f);
+	taskfile.device_head	|= drive->select.all;
+	taskfile.command	= get_command(drive, rq_data_dir(rq));
+
+#ifdef DEBUG
+	printk("%s: %sing: ", drive->name,
+		(rq_data_dir(rq)==READ) ? "read" : "writ");
+	if (lba)	printk("LBAsect=%lld, ", block);
+	else		printk("CHS=%d/%d/%d, ", cyl, head, sect);
+	printk("sectors=%ld, ", rq->nr_sectors);
+	printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);
+#endif
+
+	args.taskfile = taskfile;
+	args.hobfile = hobfile;
+	ide_cmd_type_parser(&args);
+	rq->special = &args;
+
+	return ata_taskfile(drive,
+			&args.taskfile,
+			&args.hobfile,
+			args.handler,
+			args.prehandler,
+			rq);
+}
+
+/*
+ * 268435455  == 137439 MB or 28bit limit
+ * 320173056  == 163929 MB or 48bit addressing
+ * 1073741822 == 549756 MB or 48bit addressing fake drive
+ */
+
+static ide_startstop_t lba48_do_request(ide_drive_t *drive, struct request *rq, unsigned long long block)
+{
+	struct hd_drive_task_hdr	taskfile;
+	struct hd_drive_hob_hdr		hobfile;
+	ide_task_t			args;
+	int				sectors;
+
+	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
+	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
+
+	sectors = rq->nr_sectors;
+	if (sectors == 65536)
+		sectors = 0;
+
+	taskfile.sector_count	= sectors;
+	hobfile.sector_count	= sectors >> 8;
+
+	if (rq->nr_sectors == 65536) {
+		taskfile.sector_count	= 0x00;
+		hobfile.sector_count	= 0x00;
+	}
+
+	taskfile.sector_number	= block;		/* low lba */
+	taskfile.low_cylinder	= (block >>= 8);	/* mid lba */
+	taskfile.high_cylinder	= (block >>= 8);	/* hi  lba */
+
+	hobfile.sector_number	= (block >>= 8);	/* low lba */
+	hobfile.low_cylinder	= (block >>= 8);	/* mid lba */
+	hobfile.high_cylinder	= (block >>= 8);	/* hi  lba */
+
+	taskfile.device_head	= drive->select.all;
+	hobfile.device_head	= taskfile.device_head;
+	hobfile.control		= (drive->ctl|0x80);
+	taskfile.command	= get_command(drive, rq_data_dir(rq));
+
+#ifdef DEBUG
+	printk("%s: %sing: ", drive->name,
+		(rq_data_dir(rq)==READ) ? "read" : "writ");
+	if (lba)	printk("LBAsect=%lld, ", block);
+	else		printk("CHS=%d/%d/%d, ", cyl, head, sect);
+	printk("sectors=%ld, ", rq->nr_sectors);
+	printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);
+#endif
+
+	args.taskfile = taskfile;
+	args.hobfile = hobfile;
+	ide_cmd_type_parser(&args);
+	rq->special = &args;
+
+	return ata_taskfile(drive,
+			&args.taskfile,
+			&args.hobfile,
+			args.handler,
+			args.prehandler,
+			rq);
+}
 
 /*
  * Issue a READ or WRITE command to a disk, using LBA if supported, or CHS
@@ -123,7 +323,7 @@
 
 	while (drive->blocked) {
 		yield();
-		// panic("ide: Request while drive blocked?");
+		printk("ide: Request while drive blocked?");
 	}
 
 	if (!(rq->flags & REQ_CMD)) {
@@ -150,193 +350,20 @@
 	return chs_do_request(drive, rq, block);
 }
 
-static task_ioreg_t get_command(ide_drive_t *drive, int cmd)
-{
-	int lba48bit = (drive->id->cfs_enable_2 & 0x0400) ? 1 : 0;
-
-#if 1
-	lba48bit = drive->addressing;
-#endif
-
-	if (cmd == READ) {
-		if (drive->using_dma)
-			return (lba48bit) ? WIN_READDMA_EXT : WIN_READDMA;
-		else if (drive->mult_count)
-			return (lba48bit) ? WIN_MULTREAD_EXT : WIN_MULTREAD;
-		else
-			return (lba48bit) ? WIN_READ_EXT : WIN_READ;
-	} else if (cmd == WRITE) {
-		if (drive->using_dma)
-			return (lba48bit) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
-		else if (drive->mult_count)
-			return (lba48bit) ? WIN_MULTWRITE_EXT : WIN_MULTWRITE;
-		else
-			return (lba48bit) ? WIN_WRITE_EXT : WIN_WRITE;
-	}
-	return WIN_NOP;
-}
-
-static ide_startstop_t chs_do_request(ide_drive_t *drive, struct request *rq, unsigned long block)
-{
-	struct hd_drive_task_hdr	taskfile;
-	struct hd_drive_hob_hdr		hobfile;
-	ide_task_t			args;
-	int				sectors;
-
-	task_ioreg_t command	= get_command(drive, rq_data_dir(rq));
-
-	unsigned int track	= (block / drive->sect);
-	unsigned int sect	= (block % drive->sect) + 1;
-	unsigned int head	= (track % drive->head);
-	unsigned int cyl	= (track / drive->head);
-
-	memset(&taskfile, 0, sizeof(task_struct_t));
-	memset(&hobfile, 0, sizeof(hob_struct_t));
-
-	sectors = rq->nr_sectors;
-	if (sectors == 256)
-		sectors = 0;
-
-	taskfile.sector_count	= sectors;
-	taskfile.sector_number	= sect;
-	taskfile.low_cylinder	= cyl;
-	taskfile.high_cylinder	= (cyl>>8);
-	taskfile.device_head	= head;
-	taskfile.device_head	|= drive->select.all;
-	taskfile.command	= command;
-
-#ifdef DEBUG
-	printk("%s: %sing: ", drive->name,
-		(rq_data_dir(rq)==READ) ? "read" : "writ");
-	if (lba)	printk("LBAsect=%lld, ", block);
-	else		printk("CHS=%d/%d/%d, ", cyl, head, sect);
-	printk("sectors=%ld, ", rq->nr_sectors);
-	printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);
-#endif
-
-	memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
-	memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr));
-	ide_cmd_type_parser(&args);
-	args.rq	= rq;
-	args.block = block;
-	rq->special = &args;
-
-	return do_rw_taskfile(drive, &args);
-}
-
-static ide_startstop_t lba28_do_request(ide_drive_t *drive, struct request *rq, unsigned long block)
-{
-	struct hd_drive_task_hdr	taskfile;
-	struct hd_drive_hob_hdr		hobfile;
-	ide_task_t			args;
-	int				sectors;
-
-	task_ioreg_t command	= get_command(drive, rq_data_dir(rq));
-
-	sectors = rq->nr_sectors;
-	if (sectors == 256)
-		sectors = 0;
-
-	memset(&taskfile, 0, sizeof(task_struct_t));
-	memset(&hobfile, 0, sizeof(hob_struct_t));
-
-	taskfile.sector_count	= sectors;
-	taskfile.sector_number	= block;
-	taskfile.low_cylinder	= (block>>=8);
-	taskfile.high_cylinder	= (block>>=8);
-	taskfile.device_head	= ((block>>8)&0x0f);
-	taskfile.device_head	|= drive->select.all;
-	taskfile.command	= command;
-
-#ifdef DEBUG
-	printk("%s: %sing: ", drive->name,
-		(rq_data_dir(rq)==READ) ? "read" : "writ");
-	if (lba)	printk("LBAsect=%lld, ", block);
-	else		printk("CHS=%d/%d/%d, ", cyl, head, sect);
-	printk("sectors=%ld, ", rq->nr_sectors);
-	printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);
-#endif
-
-	memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
-	memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr));
-	ide_cmd_type_parser(&args);
-	args.rq = rq;
-	args.block = block;
-	rq->special = &args;
-
-	return do_rw_taskfile(drive, &args);
-}
-
-/*
- * 268435455  == 137439 MB or 28bit limit
- * 320173056  == 163929 MB or 48bit addressing
- * 1073741822 == 549756 MB or 48bit addressing fake drive
- */
-
-static ide_startstop_t lba48_do_request(ide_drive_t *drive, struct request *rq, unsigned long long block)
-{
-	struct hd_drive_task_hdr	taskfile;
-	struct hd_drive_hob_hdr		hobfile;
-	ide_task_t			args;
-	int				sectors;
-
-	task_ioreg_t command	= get_command(drive, rq_data_dir(rq));
-
-	memset(&taskfile, 0, sizeof(task_struct_t));
-	memset(&hobfile, 0, sizeof(hob_struct_t));
-
-	sectors = rq->nr_sectors;
-	if (sectors == 65536)
-		sectors = 0;
-
-	taskfile.sector_count	= sectors;
-	hobfile.sector_count	= sectors >> 8;
-
-	if (rq->nr_sectors == 65536) {
-		taskfile.sector_count	= 0x00;
-		hobfile.sector_count	= 0x00;
-	}
-
-	taskfile.sector_number	= block;	/* low lba */
-	taskfile.low_cylinder	= (block>>=8);	/* mid lba */
-	taskfile.high_cylinder	= (block>>=8);	/* hi  lba */
-	hobfile.sector_number	= (block>>=8);	/* low lba */
-	hobfile.low_cylinder	= (block>>=8);	/* mid lba */
-	hobfile.high_cylinder	= (block>>=8);	/* hi  lba */
-	taskfile.device_head	= drive->select.all;
-	hobfile.device_head	= taskfile.device_head;
-	hobfile.control		= (drive->ctl|0x80);
-	taskfile.command	= command;
-
-#ifdef DEBUG
-	printk("%s: %sing: ", drive->name,
-		(rq_data_dir(rq)==READ) ? "read" : "writ");
-	if (lba)	printk("LBAsect=%lld, ", block);
-	else		printk("CHS=%d/%d/%d, ", cyl, head, sect);
-	printk("sectors=%ld, ", rq->nr_sectors);
-	printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);
-#endif
-
-	memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
-	memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr));
-	ide_cmd_type_parser(&args);
-	args.rq = rq;
-	args.block = block;
-	rq->special = &args;
-
-	return do_rw_taskfile(drive, &args);
-}
-
 static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *drive)
 {
 	MOD_INC_USE_COUNT;
 	if (drive->removable && drive->usage == 1) {
 		struct hd_drive_task_hdr taskfile;
 		struct hd_drive_hob_hdr hobfile;
+
 		memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
 		memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
+
 		check_disk_change(inode->i_rdev);
+
 		taskfile.command = WIN_DOORLOCK;
+
 		/*
 		 * Ignore the return code from door_lock,
 		 * since the open() has already succeeded,
@@ -353,13 +380,14 @@
 {
 	struct hd_drive_task_hdr taskfile;
 	struct hd_drive_hob_hdr hobfile;
+
 	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
 	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
-	if (drive->id->cfs_enable_2 & 0x2400) {
-		taskfile.command	= WIN_FLUSH_CACHE_EXT;
-	} else {
-		taskfile.command	= WIN_FLUSH_CACHE;
-	}
+	if (drive->id->cfs_enable_2 & 0x2400)
+		taskfile.command = WIN_FLUSH_CACHE_EXT;
+	else
+		taskfile.command = WIN_FLUSH_CACHE;
+
 	return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
 }
 
@@ -368,9 +396,12 @@
 	if (drive->removable && !drive->usage) {
 		struct hd_drive_task_hdr taskfile;
 		struct hd_drive_hob_hdr hobfile;
+
 		memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
 		memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
+
 		invalidate_bdev(inode->i_bdev, 0);
+
 		taskfile.command = WIN_DOORUNLOCK;
 		if (drive->doorlocking &&
 		    ide_wait_taskfile(drive, &taskfile, &hobfile, NULL))
@@ -404,21 +435,23 @@
 
 	/* Create IDE/ATA command request structure */
 	memset(&args, 0, sizeof(ide_task_t));
-	args.tfRegister[IDE_SELECT_OFFSET]	= 0x40;
-	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_READ_NATIVE_MAX;
-	args.handler				= task_no_data_intr;
+	args.taskfile.device_head = 0x40;
+	args.taskfile.command = WIN_READ_NATIVE_MAX;
+	args.handler = task_no_data_intr;
 
 	/* submit command request */
 	ide_raw_taskfile(drive, &args, NULL);
 
 	/* if OK, compute maximum address value */
-	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
-		addr = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)
-		     | ((args.tfRegister[  IDE_HCYL_OFFSET]       ) << 16)
-		     | ((args.tfRegister[  IDE_LCYL_OFFSET]       ) <<  8)
-		     | ((args.tfRegister[IDE_SECTOR_OFFSET]       ));
+	if ((args.taskfile.command & 0x01) == 0) {
+		addr = ((args.taskfile.device_head & 0x0f) << 24)
+		     | (args.taskfile.high_cylinder << 16)
+		     | (args.taskfile.low_cylinder <<  8)
+		     | args.taskfile.sector_number;
 	}
+
 	addr++;	/* since the return value is (maxlba - 1), we add 1 */
+
 	return addr;
 }
 
@@ -430,24 +463,26 @@
 	/* Create IDE/ATA command request structure */
 	memset(&args, 0, sizeof(ide_task_t));
 
-	args.tfRegister[IDE_SELECT_OFFSET]	= 0x40;
-	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_READ_NATIVE_MAX_EXT;
-	args.handler				= task_no_data_intr;
+	args.taskfile.device_head = 0x40;
+	args.taskfile.command = WIN_READ_NATIVE_MAX_EXT;
+	args.handler = task_no_data_intr;
 
         /* submit command request */
         ide_raw_taskfile(drive, &args, NULL);
 
 	/* if OK, compute maximum address value */
-	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
-		u32 high = ((args.hobRegister[IDE_HCYL_OFFSET_HOB])<<16) |
-			   ((args.hobRegister[IDE_LCYL_OFFSET_HOB])<<8) |
-			    (args.hobRegister[IDE_SECTOR_OFFSET_HOB]);
-		u32 low  = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |
-			   ((args.tfRegister[IDE_LCYL_OFFSET])<<8) |
-			    (args.tfRegister[IDE_SECTOR_OFFSET]);
+	if ((args.taskfile.command & 0x01) == 0) {
+		u32 high = (args.hobfile.high_cylinder << 16) |
+			   (args.hobfile.low_cylinder << 8) |
+			    args.hobfile.sector_number;
+		u32 low  = (args.taskfile.high_cylinder << 16) |
+			   (args.taskfile.low_cylinder << 8) |
+			    args.taskfile.sector_number;
 		addr = ((__u64)high << 24) | low;
 	}
+
 	addr++;	/* since the return value is (maxlba - 1), we add 1 */
+
 	return addr;
 }
 
@@ -464,20 +499,22 @@
 	addr_req--;
 	/* Create IDE/ATA command request structure */
 	memset(&args, 0, sizeof(ide_task_t));
-	args.tfRegister[IDE_SECTOR_OFFSET]	= ((addr_req >>  0) & 0xff);
-	args.tfRegister[IDE_LCYL_OFFSET]	= ((addr_req >>  8) & 0xff);
-	args.tfRegister[IDE_HCYL_OFFSET]	= ((addr_req >> 16) & 0xff);
-	args.tfRegister[IDE_SELECT_OFFSET]	= ((addr_req >> 24) & 0x0f) | 0x40;
-	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SET_MAX;
-	args.handler				= task_no_data_intr;
+
+	args.taskfile.sector_number = (addr_req >> 0);
+	args.taskfile.low_cylinder = (addr_req >> 8);
+	args.taskfile.high_cylinder = (addr_req >> 16);
+
+	args.taskfile.device_head = ((addr_req >> 24) & 0x0f) | 0x40;
+	args.taskfile.command = WIN_SET_MAX;
+	args.handler = task_no_data_intr;
 	/* submit command request */
 	ide_raw_taskfile(drive, &args, NULL);
 	/* if OK, read new maximum address value */
-	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
-		addr_set = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)
-			 | ((args.tfRegister[  IDE_HCYL_OFFSET]       ) << 16)
-			 | ((args.tfRegister[  IDE_LCYL_OFFSET]       ) <<  8)
-			 | ((args.tfRegister[IDE_SECTOR_OFFSET]       ));
+	if ((args.taskfile.command & 0x01) == 0) {
+		addr_set = ((args.taskfile.device_head & 0x0f) << 24)
+			 | (args.taskfile.high_cylinder << 16)
+			 | (args.taskfile.low_cylinder <<  8)
+			 | args.taskfile.sector_number;
 	}
 	addr_set++;
 	return addr_set;
@@ -491,27 +528,31 @@
 	addr_req--;
 	/* Create IDE/ATA command request structure */
 	memset(&args, 0, sizeof(ide_task_t));
-	args.tfRegister[IDE_SECTOR_OFFSET]	= ((addr_req >>  0) & 0xff);
-	args.tfRegister[IDE_LCYL_OFFSET]	= ((addr_req >>= 8) & 0xff);
-	args.tfRegister[IDE_HCYL_OFFSET]	= ((addr_req >>= 8) & 0xff);
-	args.tfRegister[IDE_SELECT_OFFSET]      = 0x40;
-	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SET_MAX_EXT;
-	args.hobRegister[IDE_SECTOR_OFFSET_HOB]	= ((addr_req >>= 8) & 0xff);
-	args.hobRegister[IDE_LCYL_OFFSET_HOB]	= ((addr_req >>= 8) & 0xff);
-	args.hobRegister[IDE_HCYL_OFFSET_HOB]	= ((addr_req >>= 8) & 0xff);
-	args.hobRegister[IDE_SELECT_OFFSET_HOB]	= 0x40;
-	args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80);
-        args.handler				= task_no_data_intr;
+
+	args.taskfile.sector_number = (addr_req >>  0);
+	args.taskfile.low_cylinder = (addr_req >>= 8);
+	args.taskfile.high_cylinder = (addr_req >>= 8);
+	args.taskfile.device_head = 0x40;
+	args.taskfile.command = WIN_SET_MAX_EXT;
+
+	args.hobfile.sector_number = (addr_req >>= 8);
+	args.hobfile.low_cylinder = (addr_req >>= 8);
+	args.hobfile.high_cylinder = (addr_req >>= 8);
+
+	args.hobfile.device_head = 0x40;
+	args.hobfile.control = (drive->ctl | 0x80);
+
+        args.handler = task_no_data_intr;
 	/* submit command request */
 	ide_raw_taskfile(drive, &args, NULL);
 	/* if OK, compute maximum address value */
-	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
-		u32 high = ((args.hobRegister[IDE_HCYL_OFFSET_HOB])<<16) |
-			   ((args.hobRegister[IDE_LCYL_OFFSET_HOB])<<8) |
-			    (args.hobRegister[IDE_SECTOR_OFFSET_HOB]);
-		u32 low  = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |
-			   ((args.tfRegister[IDE_LCYL_OFFSET])<<8) |
-			    (args.tfRegister[IDE_SECTOR_OFFSET]);
+	if ((args.taskfile.command & 0x01) == 0) {
+		u32 high = (args.hobfile.high_cylinder << 16) |
+			   (args.hobfile.low_cylinder << 8) |
+			    args.hobfile.sector_number;
+		u32 low  = (args.taskfile.high_cylinder << 16) |
+			   (args.taskfile.low_cylinder << 8) |
+			    args.taskfile.sector_number;
 		addr_set = ((__u64)high << 24) | low;
 	}
 	return addr_set;
@@ -572,10 +613,10 @@
 				drive->select.b.lba = 1;
 				drive->id->lba_capacity_2 = capacity_2;
                         }
-#else /* !CONFIG_IDEDISK_STROKE */
+#else
 			printk("%s: setmax_ext LBA %llu, native  %llu\n",
 				drive->name, set_max_ext, capacity_2);
-#endif /* CONFIG_IDEDISK_STROKE */
+#endif
 		}
 		drive->bios_cyl		= drive->cyl;
 		drive->capacity48	= capacity_2;
@@ -598,10 +639,10 @@
 			drive->select.b.lba = 1;
 			drive->id->lba_capacity = capacity;
 		}
-#else /* !CONFIG_IDEDISK_STROKE */
+#else
 		printk("%s: setmax LBA %lu, native  %lu\n",
 			drive->name, set_max, capacity);
-#endif /* CONFIG_IDEDISK_STROKE */
+#endif
 	}
 
 	drive->capacity = capacity;
@@ -643,7 +684,7 @@
 			taskfile.command = WIN_SPECIFY;
 			handler	= set_geometry_intr;;
 		}
-		do_taskfile(drive, &taskfile, &hobfile, handler);
+		ata_taskfile(drive, &taskfile, &hobfile, handler, NULL, NULL);
 	} else if (s->b.recalibrate) {
 		s->b.recalibrate = 0;
 		if (!IS_PDC4030_DRIVE) {
@@ -653,7 +694,7 @@
 			memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
 			taskfile.sector_count	= drive->sect;
 			taskfile.command	= WIN_RESTORE;
-			do_taskfile(drive, &taskfile, &hobfile, recal_intr);
+			ata_taskfile(drive, &taskfile, &hobfile, recal_intr, NULL, NULL);
 		}
 	} else if (s->b.set_multmode) {
 		s->b.set_multmode = 0;
@@ -666,7 +707,7 @@
 			memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
 			taskfile.sector_count	= drive->mult_req;
 			taskfile.command	= WIN_SETMULT;
-			do_taskfile(drive, &taskfile, &hobfile, &set_multmode_intr);
+			ata_taskfile(drive, &taskfile, &hobfile, set_multmode_intr, NULL, NULL);
 		}
 	} else if (s->all) {
 		int special = s->all;
@@ -915,6 +956,9 @@
 	 * already been done...
 	 */
 
+	if (level != SUSPEND_SAVE_STATE)
+		return 0;
+
 	/* wait until all commands are finished */
 	printk("ide_disk_suspend()\n");
 	while (HWGROUP(drive)->handler)
@@ -934,6 +978,9 @@
 static int idedisk_resume(struct device *dev, u32 level)
 {
 	ide_drive_t *drive = dev->driver_data;
+
+	if (level != RESUME_RESTORE_STATE)
+		return 0;
 	if (!drive->blocked)
 		panic("ide: Resume but not suspended?\n");
 
@@ -979,7 +1026,7 @@
 		}
 	}
 	for (i = 0; i < MAX_DRIVES; ++i) {
-		ide_hwif_t *hwif = HWIF(drive);
+		struct ata_channel *hwif = drive->channel;
 
 		if (drive != &hwif->drives[i])
 		    continue;
@@ -997,7 +1044,7 @@
 	    sprintf(drive->device.bus_id, "%d", drvid);
 	    sprintf(drive->device.name, "ide-disk");
 	    drive->device.driver = &idedisk_devdrv;
-	    drive->device.parent = &HWIF(drive)->device;
+	    drive->device.parent = &drive->channel->dev;
 	    drive->device.driver_data = drive;
 	    device_register(&drive->device);
 	}
@@ -1045,11 +1092,11 @@
 	if (id->buf_size)
 		printk (" w/%dKiB Cache", id->buf_size/2);
 
-	printk(", CHS=%d/%d/%d", 
+	printk(", CHS=%d/%d/%d",
 	       drive->bios_cyl, drive->bios_head, drive->bios_sect);
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (drive->using_dma)
-		(void) HWIF(drive)->dmaproc(ide_dma_verbose, drive);
+		(void) drive->channel->dmaproc(ide_dma_verbose, drive);
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 	printk("\n");
 
@@ -1074,8 +1121,11 @@
 	(void) probe_lba_addressing(drive, 1);
 }
 
-static int idedisk_cleanup (ide_drive_t *drive)
+static int idedisk_cleanup(ide_drive_t *drive)
 {
+	if (!drive)
+	    return 0;
+
 	put_device(&drive->device);
 	if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
 		if (idedisk_flushcache(drive))
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 9fade24..b221a3b 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -204,7 +204,7 @@
 {
 	byte stat, dma_stat;
 
-	dma_stat = HWIF(drive)->dmaproc(ide_dma_end, drive);
+	dma_stat = drive->channel->dmaproc(ide_dma_end, drive);
 	stat = GET_STAT();			/* get drive status */
 	if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
 		if (!dma_stat) {
@@ -219,7 +219,7 @@
 	return ide_error(drive, "dma_intr", stat);
 }
 
-static int ide_build_sglist (ide_hwif_t *hwif, struct request *rq)
+static int ide_build_sglist(struct ata_channel *hwif, struct request *rq)
 {
 	request_queue_t *q = &hwif->drives[DEVICE_NR(rq->rq_dev) & 1].queue;
 	struct scatterlist *sg = hwif->sg_table;
@@ -238,7 +238,7 @@
 	return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction);
 }
 
-static int ide_raw_build_sglist (ide_hwif_t *hwif, struct request *rq)
+static int ide_raw_build_sglist(struct ata_channel *hwif, struct request *rq)
 {
 	struct scatterlist *sg = hwif->sg_table;
 	int nents = 0;
@@ -285,7 +285,7 @@
  */
 int ide_build_dmatable (ide_drive_t *drive, ide_dma_action_t func)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	unsigned int *table = hwif->dmatable_cpu;
 #ifdef CONFIG_BLK_DEV_TRM290
 	unsigned int is_trm290_chipset = (hwif->chipset == ide_trm290);
@@ -371,11 +371,11 @@
 /* Teardown mappings after DMA has completed.  */
 void ide_destroy_dmatable (ide_drive_t *drive)
 {
-	struct pci_dev *dev = HWIF(drive)->pci_dev;
-	struct scatterlist *sg = HWIF(drive)->sg_table;
-	int nents = HWIF(drive)->sg_nents;
+	struct pci_dev *dev = drive->channel->pci_dev;
+	struct scatterlist *sg = drive->channel->sg_table;
+	int nents = drive->channel->sg_nents;
 
-	pci_unmap_sg(dev, sg, nents, HWIF(drive)->sg_dma_direction);
+	pci_unmap_sg(dev, sg, nents, drive->channel->sg_dma_direction);
 }
 
 /*
@@ -462,7 +462,7 @@
 {
 	int config_allows_dma = 1;
 	struct hd_driveid *id = drive->id;
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 
 #ifdef CONFIG_IDEDMA_ONLYDISK
 	if (drive->type != ATA_DISK)
@@ -502,7 +502,7 @@
  */
 static int dma_timer_expiry(ide_drive_t *drive)
 {
-	byte dma_stat = inb(HWIF(drive)->dma_base+2);
+	byte dma_stat = inb(drive->channel->dma_base+2);
 
 #ifdef DEBUG
 	printk("%s: dma_timer_expiry: dma status == 0x%02x\n", drive->name, dma_stat);
@@ -525,11 +525,11 @@
 {
 	u64 addr = BLK_BOUNCE_HIGH;
 
-	if (on && drive->type == ATA_DISK && HWIF(drive)->highmem) {
+	if (on && drive->type == ATA_DISK && drive->channel->highmem) {
 		if (!PCI_DMA_BUS_IS_PHYS)
 			addr = BLK_BOUNCE_ANY;
 		else
-			addr = HWIF(drive)->pci_dev->dma_mask;
+			addr = drive->channel->pci_dev->dma_mask;
 	}
 
 	blk_queue_bounce_limit(&drive->queue, addr);
@@ -553,7 +553,7 @@
  */
 int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	unsigned long dma_base = hwif->dma_base;
 	byte unit = (drive->select.b.unit & 0x01);
 	unsigned int count, reading = 0, set_high = 1;
@@ -588,17 +588,19 @@
 			drive->waiting_for_dma = 1;
 			if (drive->type != ATA_DISK)
 				return 0;
+
+			BUG_ON(HWGROUP(drive)->handler);
 			ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, dma_timer_expiry);	/* issue cmd to drive */
 			if ((HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) &&
 			    (drive->addressing == 1)) {
 				ide_task_t *args = HWGROUP(drive)->rq->special;
-				OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG);
+				OUT_BYTE(args->taskfile.command, IDE_COMMAND_REG);
 			} else if (drive->addressing) {
 				OUT_BYTE(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG);
 			} else {
 				OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
 			}
-			return HWIF(drive)->dmaproc(ide_dma_begin, drive);
+			return drive->channel->dmaproc(ide_dma_begin, drive);
 		case ide_dma_begin:
 			/* Note that this is done *after* the cmd has
 			 * been issued to the drive, as per the BM-IDE spec.
@@ -644,7 +646,7 @@
 /*
  * Needed for allowing full modular support of ide-driver
  */
-void ide_release_dma(ide_hwif_t *hwif)
+void ide_release_dma(struct ata_channel *hwif)
 {
 	if (!hwif->dma_base)
 		return;
@@ -660,7 +662,7 @@
 		kfree(hwif->sg_table);
 		hwif->sg_table = NULL;
 	}
-	if ((hwif->dma_extra) && (hwif->channel == 0))
+	if ((hwif->dma_extra) && (hwif->unit == 0))
 		release_region((hwif->dma_base + 16), hwif->dma_extra);
 	release_region(hwif->dma_base, 8);
 	hwif->dma_base = 0;
@@ -669,7 +671,7 @@
 /*
  * This can be called for a dynamically installed interface. Don't __init it
  */
-void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports)
+void ide_setup_dma(struct ata_channel *hwif, unsigned long dma_base, unsigned int num_ports)
 {
 	printk("    %s: BM-DMA at 0x%04lx-0x%04lx", hwif->name, dma_base, dma_base + num_ports - 1);
 	if (check_region(dma_base, num_ports)) {
diff --git a/drivers/ide/ide-features.c b/drivers/ide/ide-features.c
index 840abba..748b1e6 100644
--- a/drivers/ide/ide-features.c
+++ b/drivers/ide/ide-features.c
@@ -2,7 +2,7 @@
  * linux/drivers/block/ide-features.c	Version 0.04	June 9, 2000
  *
  *  Copyright (C) 1999-2000	Linus Torvalds & authors (see below)
- *  
+ *
  *  Copyright (C) 1999-2000	Andre Hedrick <andre@linux-ide.org>
  *
  *  Extracts if ide.c to address the evolving transfer rate code for
@@ -134,7 +134,7 @@
 	struct hd_driveid *id;
 	unsigned long timeout, flags;
 
-	SELECT_MASK(HWIF(drive), drive, 1);
+	SELECT_MASK(drive->channel, drive, 1);
 	if (IDE_CONTROL_REG)
 		OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
 	ide_delay_50ms();
@@ -142,20 +142,20 @@
 	timeout = jiffies + WAIT_WORSTCASE;
 	do {
 		if (0 < (signed long)(jiffies - timeout)) {
-			SELECT_MASK(HWIF(drive), drive, 0);
+			SELECT_MASK(drive->channel, drive, 0);
 			return 0;	/* 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)) {
-		SELECT_MASK(HWIF(drive), drive, 0);
+		SELECT_MASK(drive->channel, drive, 0);
 		printk("%s: CHECK for good STATUS\n", drive->name);
 		return 0;
 	}
 	__save_flags(flags);	/* local CPU only */
 	__cli();		/* local CPU only; some systems need this */
-	SELECT_MASK(HWIF(drive), drive, 0);
+	SELECT_MASK(drive->channel, drive, 0);
 	id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC);
 	if (!id) {
 		__restore_flags(flags);	/* local CPU only */
@@ -186,11 +186,11 @@
  */
 int ide_ata66_check (ide_drive_t *drive, ide_task_t *args)
 {
-	if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) &&
-	    (args->tfRegister[IDE_SECTOR_OFFSET] > XFER_UDMA_2) &&
-	    (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER)) {
-		if (!HWIF(drive)->udma_four) {
-			printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", HWIF(drive)->name);
+	if ((args->taskfile.command == WIN_SETFEATURES) &&
+	    (args->taskfile.sector_number > XFER_UDMA_2) &&
+	    (args->taskfile.feature == SETFEATURES_XFER)) {
+		if (!drive->channel->udma_four) {
+			printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", drive->channel->name);
 			return 1;
 		}
 #ifndef CONFIG_IDEDMA_IVB
@@ -213,9 +213,9 @@
  */
 int set_transfer (ide_drive_t *drive, ide_task_t *args)
 {
-	if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) &&
-	    (args->tfRegister[IDE_SECTOR_OFFSET] >= XFER_SW_DMA_0) &&
-	    (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER) &&
+	if ((args->taskfile.command == WIN_SETFEATURES) &&
+	    (args->taskfile.sector_number >= XFER_SW_DMA_0) &&
+	    (args->taskfile.feature == SETFEATURES_XFER) &&
 	    (drive->id->dma_ultra ||
 	     drive->id->dma_mword ||
 	     drive->id->dma_1word))
@@ -229,7 +229,7 @@
  */
 byte eighty_ninty_three (ide_drive_t *drive)
 {
-	return ((byte) ((HWIF(drive)->udma_four) &&
+	return ((byte) ((drive->channel->udma_four) &&
 #ifndef CONFIG_IDEDMA_IVB
 			(drive->id->hw_config & 0x4000) &&
 #endif /* CONFIG_IDEDMA_IVB */
@@ -249,8 +249,9 @@
  */
 int ide_config_drive_speed (ide_drive_t *drive, byte speed)
 {
-	ide_hwif_t *hwif = HWIF(drive);
-	int	i, error = 1;
+	struct ata_channel *hwif = drive->channel;
+	int i;
+	int error = 1;
 	byte stat;
 
 #if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI)
@@ -269,8 +270,8 @@
          */
 	disable_irq(hwif->irq);	/* disable_irq_nosync ?? */
 	udelay(1);
-	SELECT_DRIVE(HWIF(drive), drive);
-	SELECT_MASK(HWIF(drive), drive, 0);
+	SELECT_DRIVE(drive->channel, drive);
+	SELECT_MASK(drive->channel, drive, 0);
 	udelay(1);
 	if (IDE_CONTROL_REG)
 		OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG);
@@ -310,7 +311,7 @@
 		}
 	}
 
-	SELECT_MASK(HWIF(drive), drive, 0);
+	SELECT_MASK(drive->channel, drive, 0);
 
 	enable_irq(hwif->irq);
 
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 7581132..e988e17c 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -902,7 +902,7 @@
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
-		if (HWIF(drive)->dmaproc(ide_dma_end, drive)) {
+		if (drive->channel->dmaproc(ide_dma_end, drive)) {
 			set_bit (PC_DMA_ERROR, &pc->flags);
 		} else {
 			pc->actually_transferred=pc->request_transfer;
@@ -945,7 +945,7 @@
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
 		printk (KERN_ERR "ide-floppy: The floppy wants to issue more interrupts in DMA mode\n");
-		HWIF(drive)->dmaproc(ide_dma_off, drive);
+		drive->channel->dmaproc(ide_dma_off, drive);
 		return ide_stopped;
 	}
 #endif /* CONFIG_BLK_DEV_IDEDMA */
@@ -968,6 +968,7 @@
 			if (temp > pc->buffer_size) {
 				printk (KERN_ERR "ide-floppy: The floppy wants to send us more data than expected - discarding data\n");
 				idefloppy_discard_data (drive,bcount.all);
+				BUG_ON(HWGROUP(drive)->handler);
 				ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL);
 				return ide_started;
 			}
@@ -990,7 +991,9 @@
 	pc->actually_transferred+=bcount.all;				/* Update the current position */
 	pc->current_position+=bcount.all;
 
-	ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL);		/* And set the interrupt handler again */
+	BUG_ON(HWGROUP(drive)->handler);
+	ide_set_handler(drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL);		/* And set the interrupt handler again */
+
 	return ide_started;
 }
 
@@ -1014,8 +1017,11 @@
 		printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n");
 		return ide_stopped;
 	}
+
+	BUG_ON(HWGROUP(drive)->handler);
 	ide_set_handler (drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);	/* Set the interrupt routine */
 	atapi_output_bytes (drive, floppy->pc->c, 12); /* Send the actual packet */
+
 	return ide_started;
 }
 
@@ -1055,17 +1061,19 @@
 		printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n");
 		return ide_stopped;
 	}
-	/* 
+	/*
 	 * The following delay solves a problem with ATAPI Zip 100 drives where the
 	 * Busy flag was apparently being deasserted before the unit was ready to
 	 * receive data. This was happening on a 1200 MHz Athlon system. 10/26/01
-	 * 25msec is too short, 40 and 50msec work well. idefloppy_pc_intr will 
+	 * 25msec is too short, 40 and 50msec work well. idefloppy_pc_intr will
 	 * not be actually used until after the packet is moved in about 50 msec.
 	 */
-	ide_set_handler (drive, 
-	  &idefloppy_pc_intr, 		/* service routine for packet command */
+	BUG_ON(HWGROUP(drive)->handler);
+	ide_set_handler (drive,
+	  &idefloppy_pc_intr,		/* service routine for packet command */
 	  floppy->ticks,			/* wait this long before "failing" */
 	  &idefloppy_transfer_pc2);	/* fail == transfer_pc2 */
+
 	return ide_started;
 }
 
@@ -1117,10 +1125,10 @@
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) {
-		(void) HWIF(drive)->dmaproc(ide_dma_off, drive);
+		(void) drive->channel->dmaproc(ide_dma_off, drive);
 	}
 	if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
-		dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
+		dma_ok=!drive->channel->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
 	if (IDE_CONTROL_REG)
@@ -1133,7 +1141,7 @@
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (dma_ok) {							/* Begin DMA, if necessary */
 		set_bit (PC_DMA_IN_PROGRESS, &pc->flags);
-		(void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
+		(void) drive->channel->dmaproc(ide_dma_begin, drive);
 	}
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
@@ -1143,8 +1151,9 @@
 	} else {
 		pkt_xfer_routine = &idefloppy_transfer_pc;	/* immediate */
 	}
-	
+
 	if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) {
+		BUG_ON(HWGROUP(drive)->handler);
 		ide_set_handler (drive, pkt_xfer_routine, IDEFLOPPY_WAIT_CMD, NULL);
 		OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG);		/* Issue the packet command */
 		return ide_started;
@@ -1156,7 +1165,7 @@
 
 static void idefloppy_rw_callback (ide_drive_t *drive)
 {
-#if IDEFLOPPY_DEBUG_LOG	
+#if IDEFLOPPY_DEBUG_LOG
 	printk (KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n");
 #endif /* IDEFLOPPY_DEBUG_LOG */
 
@@ -2004,7 +2013,7 @@
 	(void) idefloppy_get_capacity (drive);
 	idefloppy_add_settings(drive);
 	for (i = 0; i < MAX_DRIVES; ++i) {
-		ide_hwif_t *hwif = HWIF(drive);
+		struct ata_channel *hwif = drive->channel;
 
 		if (drive != &hwif->drives[i]) continue;
 		hwif->gd->de_arr[i] = drive->de;
@@ -2109,10 +2118,9 @@
 			kfree (floppy);
 			continue;
 		}
-		/* ATA-PATTERN */
-		ata_ops(drive)->busy++;
+		MOD_INC_USE_COUNT;
 		idefloppy_setup (drive, floppy);
-		ata_ops(drive)->busy--;
+		MOD_DEC_USE_COUNT;
 
 		failed--;
 	}
diff --git a/drivers/ide/ide-geometry.c b/drivers/ide/ide-geometry.c
index 7a20336..0671559 100644
--- a/drivers/ide/ide-geometry.c
+++ b/drivers/ide/ide-geometry.c
@@ -7,6 +7,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/types.h>
 #include <linux/ide.h>
 #include <linux/mc146818rtc.h>
 #include <asm/io.h>
diff --git a/drivers/ide/ide-pci.c b/drivers/ide/ide-pci.c
index d8c32ac..486f3bc 100644
--- a/drivers/ide/ide-pci.c
+++ b/drivers/ide/ide-pci.c
@@ -39,45 +39,45 @@
 
 #ifdef CONFIG_BLK_DEV_AEC62XX
 extern unsigned int pci_init_aec62xx(struct pci_dev *);
-extern unsigned int ata66_aec62xx(ide_hwif_t *);
-extern void ide_init_aec62xx(ide_hwif_t *);
-extern void ide_dmacapable_aec62xx(ide_hwif_t *, unsigned long);
+extern unsigned int ata66_aec62xx(struct ata_channel *);
+extern void ide_init_aec62xx(struct ata_channel *);
+extern void ide_dmacapable_aec62xx(struct ata_channel *, unsigned long);
 #endif
 
 #ifdef CONFIG_BLK_DEV_ALI15X3
 extern unsigned int pci_init_ali15x3(struct pci_dev *);
-extern unsigned int ata66_ali15x3(ide_hwif_t *);
-extern void ide_init_ali15x3(ide_hwif_t *);
-extern void ide_dmacapable_ali15x3(ide_hwif_t *, unsigned long);
+extern unsigned int ata66_ali15x3(struct ata_channel *);
+extern void ide_init_ali15x3(struct ata_channel *);
+extern void ide_dmacapable_ali15x3(struct ata_channel *, unsigned long);
 #endif
 
 #ifdef CONFIG_BLK_DEV_AMD74XX
 extern unsigned int pci_init_amd74xx(struct pci_dev *);
-extern unsigned int ata66_amd74xx(ide_hwif_t *);
-extern void ide_init_amd74xx(ide_hwif_t *);
-extern void ide_dmacapable_amd74xx(ide_hwif_t *, unsigned long);
+extern unsigned int ata66_amd74xx(struct ata_channel *);
+extern void ide_init_amd74xx(struct ata_channel *);
+extern void ide_dmacapable_amd74xx(struct ata_channel *, unsigned long);
 #endif
 
 #ifdef CONFIG_BLK_DEV_CMD64X
 extern unsigned int pci_init_cmd64x(struct pci_dev *);
-extern unsigned int ata66_cmd64x(ide_hwif_t *);
-extern void ide_init_cmd64x(ide_hwif_t *);
-extern void ide_dmacapable_cmd64x(ide_hwif_t *, unsigned long);
+extern unsigned int ata66_cmd64x(struct ata_channel *);
+extern void ide_init_cmd64x(struct ata_channel *);
+extern void ide_dmacapable_cmd64x(struct ata_channel *, unsigned long);
 #endif
 
 #ifdef CONFIG_BLK_DEV_CY82C693
 extern unsigned int pci_init_cy82c693(struct pci_dev *);
-extern void ide_init_cy82c693(ide_hwif_t *);
+extern void ide_init_cy82c693(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_CS5530
 extern unsigned int pci_init_cs5530(struct pci_dev *);
-extern void ide_init_cs5530(ide_hwif_t *);
+extern void ide_init_cs5530(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_HPT34X
 extern unsigned int pci_init_hpt34x(struct pci_dev *);
-extern void ide_init_hpt34x(ide_hwif_t *);
+extern void ide_init_hpt34x(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_HPT366
@@ -85,9 +85,9 @@
 extern byte hpt363_shared_pin;
 
 extern unsigned int pci_init_hpt366(struct pci_dev *);
-extern unsigned int ata66_hpt366(ide_hwif_t *);
-extern void ide_init_hpt366(ide_hwif_t *);
-extern void ide_dmacapable_hpt366(ide_hwif_t *, unsigned long);
+extern unsigned int ata66_hpt366(struct ata_channel *);
+extern void ide_init_hpt366(struct ata_channel *);
+extern void ide_dmacapable_hpt366(struct ata_channel *, unsigned long);
 #else
 /* FIXME: those have to be killed */
 static byte hpt363_shared_irq;
@@ -95,69 +95,69 @@
 #endif
 
 #ifdef CONFIG_BLK_DEV_NS87415
-extern void ide_init_ns87415(ide_hwif_t *);
+extern void ide_init_ns87415(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_OPTI621
-extern void ide_init_opti621(ide_hwif_t *);
+extern void ide_init_opti621(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_PDC_ADMA
 extern unsigned int pci_init_pdcadma(struct pci_dev *);
-extern unsigned int ata66_pdcadma(ide_hwif_t *);
-extern void ide_init_pdcadma(ide_hwif_t *);
-extern void ide_dmacapable_pdcadma(ide_hwif_t *, unsigned long);
+extern unsigned int ata66_pdcadma(struct ata_channel *);
+extern void ide_init_pdcadma(struct ata_channel *);
+extern void ide_dmacapable_pdcadma(struct ata_channel *, unsigned long);
 #endif
 
 #ifdef CONFIG_BLK_DEV_PDC202XX
 extern unsigned int pci_init_pdc202xx(struct pci_dev *);
-extern unsigned int ata66_pdc202xx(ide_hwif_t *);
-extern void ide_init_pdc202xx(ide_hwif_t *);
+extern unsigned int ata66_pdc202xx(struct ata_channel *);
+extern void ide_init_pdc202xx(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_PIIX
 extern unsigned int pci_init_piix(struct pci_dev *);
-extern unsigned int ata66_piix(ide_hwif_t *);
-extern void ide_init_piix(ide_hwif_t *);
-extern void ide_dmacapable_piix(ide_hwif_t *, unsigned long);
+extern unsigned int ata66_piix(struct ata_channel *);
+extern void ide_init_piix(struct ata_channel *);
+extern void ide_dmacapable_piix(struct ata_channel *, unsigned long);
 #endif
 
 #ifdef CONFIG_BLK_DEV_IT8172
 extern unsigned int pci_init_it8172(struct pci_dev *);
-extern void ide_init_it8172(ide_hwif_t *);
+extern void ide_init_it8172(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_RZ1000
-extern void ide_init_rz1000(ide_hwif_t *);
+extern void ide_init_rz1000(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_SVWKS
 extern unsigned int pci_init_svwks(struct pci_dev *);
-extern unsigned int ata66_svwks(ide_hwif_t *);
-extern void ide_init_svwks(ide_hwif_t *);
+extern unsigned int ata66_svwks(struct ata_channel *);
+extern void ide_init_svwks(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_SIS5513
 extern unsigned int pci_init_sis5513(struct pci_dev *);
-extern unsigned int ata66_sis5513(ide_hwif_t *);
-extern void ide_init_sis5513(ide_hwif_t *);
+extern unsigned int ata66_sis5513(struct ata_channel *);
+extern void ide_init_sis5513(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_SL82C105
 extern unsigned int pci_init_sl82c105(struct pci_dev *);
-extern void dma_init_sl82c105(ide_hwif_t *, unsigned long);
-extern void ide_init_sl82c105(ide_hwif_t *);
+extern void dma_init_sl82c105(struct ata_channel *, unsigned long);
+extern void ide_init_sl82c105(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_TRM290
-extern void ide_init_trm290(ide_hwif_t *);
+extern void ide_init_trm290(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_VIA82CXXX
 extern unsigned int pci_init_via82cxxx(struct pci_dev *);
-extern unsigned int ata66_via82cxxx(ide_hwif_t *);
-extern void ide_init_via82cxxx(ide_hwif_t *);
-extern void ide_dmacapable_via82cxxx(ide_hwif_t *, unsigned long);
+extern unsigned int ata66_via82cxxx(struct ata_channel *);
+extern void ide_init_via82cxxx(struct ata_channel *);
+extern void ide_dmacapable_via82cxxx(struct ata_channel *, unsigned long);
 #endif
 
 typedef struct ide_pci_enablebit_s {
@@ -181,9 +181,9 @@
 	unsigned short		vendor;
 	unsigned short		device;
 	unsigned int		(*init_chipset)(struct pci_dev *dev);
-	unsigned int		(*ata66_check)(ide_hwif_t *hwif);
-	void			(*init_hwif)(ide_hwif_t *hwif);
-	void			(*dma_init)(ide_hwif_t *hwif, unsigned long dmabase);
+	unsigned int		(*ata66_check)(struct ata_channel *hwif);
+	void			(*init_hwif)(struct ata_channel *hwif);
+	void			(*dma_init)(struct ata_channel *hwif, unsigned long dmabase);
 	ide_pci_enablebit_t	enablebits[2];
 	unsigned int		bootable;
 	unsigned int		extra;
@@ -229,6 +229,7 @@
 	{PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268R, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0, ATA_F_IRQ  | ATA_F_DMA },
 	{PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0, ATA_F_IRQ | ATA_F_DMA },
 	{PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275, pci_init_pdc202xx, ata66_pdc202xx,	ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0, ATA_F_IRQ | ATA_F_DMA },
+	{PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20276, pci_init_pdc202xx, ata66_pdc202xx,	ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0, ATA_F_IRQ | ATA_F_DMA },
 #endif
 #ifdef CONFIG_BLK_DEV_RZ1000
 	{PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, NULL, NULL,	ide_init_rz1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 },
@@ -328,10 +329,10 @@
  * Match a PCI IDE port against an entry in ide_hwifs[],
  * based on io_base port if possible.
  */
-static ide_hwif_t __init *lookup_hwif (unsigned long io_base, int bootable, const char *name)
+static struct ata_channel __init *lookup_hwif (unsigned long io_base, int bootable, const char *name)
 {
 	int h;
-	ide_hwif_t *hwif;
+	struct ata_channel *hwif;
 
 	/*
 	 * Look for a hwif with matching io_base specified using
@@ -430,7 +431,7 @@
 /*
  * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space:
  */
-static unsigned long __init get_dma_base(ide_hwif_t *hwif, int extra, const char *name)
+static unsigned long __init get_dma_base(struct ata_channel *hwif, int extra, const char *name)
 {
 	unsigned long	dma_base = 0;
 	struct pci_dev	*dev = hwif->pci_dev;
@@ -441,7 +442,7 @@
 	 */
 
 	if (hwif->mate && hwif->mate->dma_base)
-		dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8);
+		dma_base = hwif->mate->dma_base - (hwif->unit ? 0 : 8);
 	else
 		dma_base = pci_resource_start(dev, 4);
 
@@ -451,7 +452,7 @@
 	if (extra) /* PDC20246, PDC20262, HPT343, & HPT366 */
 		request_region(dma_base + 16, extra, name);
 
-	dma_base += hwif->channel ? 8 : 0;
+	dma_base += hwif->unit ? 8 : 0;
 	hwif->dma_extra = extra;
 
 	if ((dev->vendor == PCI_VENDOR_ID_AL && dev->device == PCI_DEVICE_ID_AL_M5219) ||
@@ -484,11 +485,11 @@
 /*
  * Setup DMA transfers on a channel.
  */
-static void __init setup_channel_dma(ide_hwif_t *hwif, struct pci_dev *dev,
+static void __init setup_channel_dma(struct ata_channel *hwif, struct pci_dev *dev,
 		ide_pci_device_t *d,
 		int port,
 		u8 class_rev,
-		int pciirq, ide_hwif_t **mate,
+		int pciirq, struct ata_channel **mate,
 		int autodma, unsigned short *pcicmd)
 {
 	unsigned long dma_base;
@@ -535,14 +536,15 @@
 		ide_pci_device_t *d,
 		int port,
 		u8 class_rev,
-		int pciirq, ide_hwif_t **mate,
+		int pciirq,
+		struct ata_channel **mate,
 		int autodma,
 		unsigned short *pcicmd)
 {
 	unsigned long base = 0;
 	unsigned long ctl = 0;
 	ide_pci_enablebit_t *e = &(d->enablebits[port]);
-	ide_hwif_t *hwif;
+	struct ata_channel *hwif;
 
 	u8 tmp;
 	if (port == 1) {
@@ -608,7 +610,7 @@
 
 	hwif->chipset = ide_pci;
 	hwif->pci_dev = dev;
-	hwif->channel = port;
+	hwif->unit = port;
 	if (!hwif->irq)
 		hwif->irq = pciirq;
 
@@ -669,7 +671,7 @@
 	int pciirq = 0;
 	unsigned short pcicmd = 0;
 	unsigned short tried_config = 0;
-	ide_hwif_t *mate = NULL;
+	struct ata_channel *mate = NULL;
 	unsigned int class_rev;
 
 #ifdef CONFIG_IDEDMA_AUTO
diff --git a/drivers/ide/ide-pmac.c b/drivers/ide/ide-pmac.c
index 3a717a5..5223f54 100644
--- a/drivers/ide/ide-pmac.c
+++ b/drivers/ide/ide-pmac.c
@@ -71,6 +71,9 @@
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
 
+# define BAD_DMA_DRIVE		0
+# define GOOD_DMA_DRIVE		1
+
 typedef struct {
 	int	accessTime;
 	int	cycleTime;
@@ -124,10 +127,10 @@
 static int
 pmac_ide_find(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	ide_ioreg_t base;
 	int i;
-	
+
 	for (i=0; i<pmac_ide_count; i++) {
 		base = pmac_ide[i].regbase;
 		if (base && base == hwif->io_ports[0])
@@ -258,8 +261,8 @@
 	save_flags(flags);
 	cli();
 	udelay(1);
-	SELECT_DRIVE(HWIF(drive), drive);
-	SELECT_MASK(HWIF(drive), drive, 0);
+	SELECT_DRIVE(drive->channel, drive);
+	SELECT_MASK(drive->channel, drive, 0);
 	udelay(1);
 	if(wait_for_ready(drive)) {
 		printk(KERN_ERR "pmac_ide_do_setfeature disk not ready before SET_FEATURE!\n");
@@ -507,7 +510,7 @@
 	struct device_node *p, **pp, *removables, **rp;
 	unsigned long base;
 	int irq, big_delay;
-	ide_hwif_t *hwif;
+	struct ata_channel *hwif;
 
 	if (_machine != _MACH_Pmac)
 		return;
@@ -928,12 +931,12 @@
 	int enable = 1;
 
 	drive->using_dma = 0;
-	
+
 	idx = pmac_ide_find(drive);
 	if (idx < 0)
 		return 0;
-		
-	if (drive->media == ide_floppy)
+
+	if (drive->type == ATA_FLOPPY)
 		enable = 0;
 	if (((id->capability & 1) == 0) && !check_drive_lists(drive, GOOD_DMA_DRIVE))
 		enable = 0;
@@ -942,9 +945,9 @@
 
 	udma = 0;
 	ata4 = (pmac_ide[idx].kind == controller_kl_ata4);
-			
+
 	if(enable) {
-		if (ata4 && (drive->media == ide_disk) &&
+		if (ata4 && (drive->type == ATA_DISK) &&
 		    (id->field_valid & 0x0004) && (id->dma_ultra & 0x17)) {
 			/* UltraDMA modes. */
 			drive->using_dma = pmac_ide_udma_enable(drive, idx);
@@ -991,8 +994,9 @@
 		if (!pmac_ide_build_dmatable(drive, ix, func==ide_dma_write))
 			return 1;
 		drive->waiting_for_dma = 1;
-		if (drive->media != ide_disk)
+		if (drive->type != ATA_DISK)
 			return 0;
+		BUG_ON(HWGROUP(drive)->handler);
 		ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);
 		OUT_BYTE(func==ide_dma_write? WIN_WRITEDMA: WIN_READDMA,
 			 IDE_COMMAND_REG);
@@ -1051,12 +1055,12 @@
 static void idepmac_sleep_device(ide_drive_t *drive, int i, unsigned base)
 {
 	int j;
-	
+
 	/* FIXME: We only handle the master IDE disk, we shoud
 	 *        try to fix CD-ROMs here
 	 */
-	switch (drive->media) {
-	case ide_disk:
+	switch (drive->type) {
+	case ATA_DISK:
 		/* Spin down the drive */
 		outb(0xa0, base+0x60);
 		outb(0x0, base+0x30);
@@ -1064,7 +1068,7 @@
 		outb(0x0, base+0x40);
 		outb(0x0, base+0x50);
 		outb(0xe0, base+0x70);
-		outb(0x2, base+0x160);   
+		outb(0x2, base+0x160);
 		for (j = 0; j < 10; j++) {
 			int status;
 			mdelay(100);
@@ -1073,10 +1077,10 @@
 				break;
 		}
 		break;
-	case ide_cdrom:
+	case ATA_ROM:
 		// todo
 		break;
-	case ide_floppy:
+	case ATA_FLOPPY:
 		// todo
 		break;
 	}
@@ -1094,7 +1098,7 @@
 		DRIVER(drive)->media_change(drive);
 
 	/* We kick the VFS too (see fix in ide.c revalidate) */
-	check_disk_change(MKDEV(HWIF(drive)->major, (drive->select.b.unit) << PARTN_BITS));
+	check_disk_change(MKDEV(drive->channel->major, (drive->select.b.unit) << PARTN_BITS));
 	
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
 	/* We re-enable DMA on the drive if it was active. */
@@ -1198,7 +1202,7 @@
 		break;
 	case PBOOK_SLEEP_NOW:
 		for (i = 0; i < pmac_ide_count; ++i) {
-			ide_hwif_t *hwif;
+			struct ata_channel *hwif;
 			ide_drive_t *drive;
 			int unlock = 0;
 
@@ -1258,8 +1262,8 @@
 			mdelay(IDE_WAKEUP_DELAY_MS);
 	
 		for (i = 0; i < pmac_ide_count; ++i) {
-			ide_hwif_t *hwif;
-			ide_drive_t *drive;			
+			struct ata_channel *hwif;
+			ide_drive_t *drive;
 			int j, used_dma;
 			
 			if ((base = pmac_ide[i].regbase) == 0)
diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c
index 462de45..818689e 100644
--- a/drivers/ide/ide-pnp.c
+++ b/drivers/ide/ide-pnp.c
@@ -13,7 +13,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * (for example /usr/src/linux/COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #include <linux/ide.h>
@@ -57,7 +57,7 @@
 static int __init pnpide_generic_init(struct pci_dev *dev, int enable)
 {
 	hw_regs_t hw;
-	ide_hwif_t *hwif;
+	struct ata_channel *hwif;
 	int index;
 
 	if (!enable)
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 69444ac..a7857ce 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -118,7 +118,7 @@
 		byte type = (id->config >> 8) & 0x1f;
 		printk("ATAPI ");
 #ifdef CONFIG_BLK_DEV_PDC4030
-		if (HWIF(drive)->channel == 1 && HWIF(drive)->chipset == ide_pdc4030) {
+		if (drive->channel->unit == 1 && drive->channel->chipset == ide_pdc4030) {
 			printk(" -- not supported on 2nd Promise port\n");
 			goto err_misc;
 		}
@@ -167,12 +167,16 @@
 	 */
 	if (id->config & (1<<7))
 		drive->removable = 1;
+
 	/*
-	 * Prevent long system lockup probing later for non-existant
-	 * slave drive if the hwif is actually a flash memory card of some variety:
+	 * FIXME: This is just plain ugly or plain unnecessary.
+	 *
+	 * Prevent long system lockup probing later for non-existant slave
+	 * drive if the hwif is actually a flash memory card of some variety:
 	 */
+
 	if (drive_is_flashcard(drive)) {
-		ide_drive_t *mate = &HWIF(drive)->drives[1^drive->select.b.unit];
+		ide_drive_t *mate = &drive->channel->drives[1 ^ drive->select.b.unit];
 		if (!mate->ata_flash) {
 			mate->present = 0;
 			mate->noprobe = 1;
@@ -182,8 +186,8 @@
 	printk("ATA DISK drive\n");
 
 	/* Initialize our quirk list. */
-	if (HWIF(drive)->quirkproc)
-		drive->quirk_list = HWIF(drive)->quirkproc(drive);
+	if (drive->channel->quirkproc)
+		drive->quirk_list = drive->channel->quirkproc(drive);
 
 	return;
 
@@ -232,7 +236,7 @@
 		OUT_BYTE(0,IDE_FEATURE_REG);	/* disable dma & overlap */
 
 #if CONFIG_BLK_DEV_PDC4030
-	if (HWIF(drive)->chipset == ide_pdc4030) {
+	if (drive->channel->chipset == ide_pdc4030) {
 		/* DC4030 hosted drives need their own identify... */
 		extern int pdc4030_identify(ide_drive_t *);
 		if (pdc4030_identify(drive)) {
@@ -270,7 +274,7 @@
 	int autoprobe = 0;
 	unsigned long cookie = 0;
 
-	if (IDE_CONTROL_REG && !HWIF(drive)->irq) {
+	if (IDE_CONTROL_REG && !drive->channel->irq) {
 		autoprobe = 1;
 		cookie = probe_irq_on();
 		OUT_BYTE(drive->ctl,IDE_CONTROL_REG);	/* enable device irq */
@@ -284,9 +288,9 @@
 		GET_STAT();			/* clear drive IRQ */
 		udelay(5);
 		irq = probe_irq_off(cookie);
-		if (!HWIF(drive)->irq) {
+		if (!drive->channel->irq) {
 			if (irq > 0)
-				HWIF(drive)->irq = irq;
+				drive->channel->irq = irq;
 			else	/* Mmmm.. multiple IRQs.. don't know which was ours */
 				printk("%s: IRQ probe failed (0x%lx)\n", drive->name, cookie);
 		}
@@ -314,7 +318,7 @@
 static int do_probe (ide_drive_t *drive, byte cmd)
 {
 	int rc;
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	if (drive->present) {	/* avoid waiting for inappropriate probes */
 		if ((drive->type != ATA_DISK) && (cmd == WIN_IDENTIFY))
 			return 4;
@@ -369,12 +373,12 @@
 /*
  *
  */
-static void enable_nest (ide_drive_t *drive)
+static void enable_nest(ide_drive_t *drive)
 {
 	unsigned long timeout;
 
-	printk("%s: enabling %s -- ", HWIF(drive)->name, drive->id->model);
-	SELECT_DRIVE(HWIF(drive), drive);
+	printk("%s: enabling %s -- ", drive->channel->name, drive->id->model);
+	SELECT_DRIVE(drive->channel, drive);
 	ide_delay_50ms();
 	OUT_BYTE(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG);
 	timeout = jiffies + WAIT_WORSTCASE;
@@ -427,7 +431,7 @@
  * ordered sanely.  We deal with the CONTROL register
  * separately.
  */
-static int hwif_check_regions (ide_hwif_t *hwif)
+static int hwif_check_regions(struct ata_channel *hwif)
 {
 	int region_errors = 0;
 
@@ -453,20 +457,20 @@
 	return(region_errors);
 }
 
-static void hwif_register (ide_hwif_t *hwif)
+static void hwif_register(struct ata_channel *hwif)
 {
 	/* Register this hardware interface within the global device tree.
 	 */
-	sprintf(hwif->device.bus_id, "%04x", hwif->io_ports[IDE_DATA_OFFSET]);
-	sprintf(hwif->device.name, "ide");
-	hwif->device.driver_data = hwif;
+	sprintf(hwif->dev.bus_id, "%04x", hwif->io_ports[IDE_DATA_OFFSET]);
+	sprintf(hwif->dev.name, "ide");
+	hwif->dev.driver_data = hwif;
 #ifdef CONFIG_BLK_DEV_IDEPCI
 	if (hwif->pci_dev)
-		hwif->device.parent = &hwif->pci_dev->dev;
+		hwif->dev.parent = &hwif->pci_dev->dev;
 	else
 #endif
-		hwif->device.parent = NULL; /* Would like to do = &device_legacy */
-	device_register(&hwif->device);
+		hwif->dev.parent = NULL; /* Would like to do = &device_legacy */
+	device_register(&hwif->dev);
 
 	if (((unsigned long)hwif->io_ports[IDE_DATA_OFFSET] | 7) ==
 	    ((unsigned long)hwif->io_ports[IDE_STATUS_OFFSET])) {
@@ -503,7 +507,7 @@
  * This routine only knows how to look for drive units 0 and 1
  * on an interface, so any setting of MAX_DRIVES > 2 won't work here.
  */
-static void probe_hwif (ide_hwif_t *hwif)
+static void probe_hwif(struct ata_channel *hwif)
 {
 	unsigned int unit;
 	unsigned long flags;
@@ -513,7 +517,7 @@
 
 	if (
 #if CONFIG_BLK_DEV_PDC4030
-	    (hwif->chipset != ide_pdc4030 || hwif->channel == 0) &&
+	    (hwif->chipset != ide_pdc4030 || hwif->unit == 0) &&
 #endif
 	    hwif_check_regions(hwif)) {
 		int msgout = 0;
@@ -562,7 +566,7 @@
 	for (unit = 0; unit < MAX_DRIVES; ++unit) {
 		ide_drive_t *drive = &hwif->drives[unit];
 		if (drive->present) {
-			ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc;
+			ide_tuneproc_t *tuneproc = drive->channel->tuneproc;
 			if (tuneproc != NULL && drive->autotune == 1)
 				tuneproc(drive, 255);	/* auto-tune PIO mode */
 		}
@@ -583,7 +587,7 @@
 
 	/* IDE can do up to 128K per request, pdc4030 needs smaller limit */
 #ifdef CONFIG_BLK_DEV_PDC4030
-	if (HWIF(drive)->chipset == ide_pdc4030)
+	if (drive->channel->chipset == ide_pdc4030)
 		max_sectors = 127;
 #endif
 	blk_queue_max_sectors(q, max_sectors);
@@ -608,9 +612,10 @@
  *
  * This routine detects and reports such situations, but does not fix them.
  */
-static void save_match(ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match)
+static void save_match(struct ata_channel *hwif, struct ata_channel *new,
+		struct ata_channel **match)
 {
-	ide_hwif_t *m = *match;
+	struct ata_channel *m = *match;
 
 	if (m && m->hwgroup && m->hwgroup != new->hwgroup) {
 		if (!new->hwgroup)
@@ -635,12 +640,12 @@
  * but anything else has led to problems on some machines.  We re-enable
  * interrupts as much as we can safely do in most places.
  */
-static int init_irq (ide_hwif_t *hwif)
+static int init_irq(struct ata_channel *hwif)
 {
 	unsigned long flags;
 	unsigned int index;
 	ide_hwgroup_t *hwgroup, *new_hwgroup;
-	ide_hwif_t *match = NULL;
+	struct ata_channel *match = NULL;
 
 
 	/* Allocate the buffer and potentially sleep first */
@@ -655,7 +660,7 @@
 	 * Group up with any other hwifs that share our irq(s).
 	 */
 	for (index = 0; index < MAX_HWIFS; index++) {
-		ide_hwif_t *h = &ide_hwifs[index];
+		struct ata_channel *h = &ide_hwifs[index];
 		if (h->hwgroup) {  /* scan only initialized hwif's */
 			if (hwif->irq == h->irq) {
 				hwif->sharing_irq = h->sharing_irq = 1;
@@ -736,7 +741,7 @@
 		ide_init_queue(drive);
 	}
 	if (!hwgroup->hwif) {
-		hwgroup->hwif = HWIF(hwgroup->drive);
+		hwgroup->hwif = hwgroup->drive->channel;
 #ifdef DEBUG
 		printk("%s : Adding missed hwif to hwgroup!!\n", hwif->name);
 #endif
@@ -770,7 +775,7 @@
  * structures needed for the routines in genhd.c.  ide_geninit() gets called
  * somewhat later, during the partition check.
  */
-static void init_gendisk (ide_hwif_t *hwif)
+static void init_gendisk(struct ata_channel *hwif)
 {
 	struct gendisk *gd;
 	unsigned int unit, minors, i;
@@ -819,11 +824,11 @@
 	for (unit = 0; unit < MAX_DRIVES; ++unit) {
 		char name[80];
 		ide_add_generic_settings(hwif->drives + unit);
-		hwif->drives[unit].dn = ((hwif->channel ? 2 : 0) + unit);
+		hwif->drives[unit].dn = ((hwif->unit ? 2 : 0) + unit);
 		sprintf (name, "host%d/bus%d/target%d/lun%d",
-			(hwif->channel && hwif->mate) ?
+			(hwif->unit && hwif->mate) ?
 			hwif->mate->index : hwif->index,
-			hwif->channel, unit, hwif->drives[unit].lun);
+			hwif->unit, unit, hwif->drives[unit].lun);
 		if (hwif->drives[unit].present)
 			hwif->drives[unit].de = devfs_mk_dir(ide_devfs_handle, name, NULL);
 	}
@@ -840,7 +845,7 @@
 	return;
 }
 
-static int hwif_init (ide_hwif_t *hwif)
+static int hwif_init(struct ata_channel *hwif)
 {
 	if (!hwif->present)
 		return 0;
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index 83f517e..a80053b 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -138,7 +138,7 @@
 static int proc_ide_read_imodel
 	(char *page, char **start, off_t off, int count, int *eof, void *data)
 {
-	ide_hwif_t	*hwif = data;
+	struct ata_channel *hwif = data;
 	int		len;
 	const char	*name;
 
@@ -167,7 +167,7 @@
 static int proc_ide_read_mate
 	(char *page, char **start, off_t off, int count, int *eof, void *data)
 {
-	ide_hwif_t	*hwif = data;
+	struct ata_channel *hwif = data;
 	int		len;
 
 	if (hwif && hwif->mate && hwif->mate->present)
@@ -180,10 +180,10 @@
 static int proc_ide_read_channel
 	(char *page, char **start, off_t off, int count, int *eof, void *data)
 {
-	ide_hwif_t	*hwif = data;
+	struct ata_channel *hwif = data;
 	int		len;
 
-	page[0] = hwif->channel ? '1' : '0';
+	page[0] = hwif->unit ? '1' : '0';
 	page[1] = '\n';
 	len = 2;
 	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
@@ -435,7 +435,7 @@
 	}
 }
 
-static void create_proc_ide_drives(ide_hwif_t *hwif)
+static void create_proc_ide_drives(struct ata_channel *hwif)
 {
 	int	d;
 	struct proc_dir_entry *ent;
@@ -465,7 +465,7 @@
 	}
 }
 
-static void destroy_proc_ide_device(ide_hwif_t *hwif, ide_drive_t *drive)
+static void destroy_proc_ide_device(struct ata_channel *hwif, ide_drive_t *drive)
 {
 	struct ata_operations *driver = drive->driver;
 
@@ -479,7 +479,7 @@
 	}
 }
 
-void destroy_proc_ide_drives(ide_hwif_t *hwif)
+void destroy_proc_ide_drives(struct ata_channel *hwif)
 {
 	int	d;
 
@@ -503,7 +503,7 @@
 	int	h;
 
 	for (h = 0; h < MAX_HWIFS; h++) {
-		ide_hwif_t *hwif = &ide_hwifs[h];
+		struct ata_channel *hwif = &ide_hwifs[h];
 
 		if (!hwif->present)
 			continue;
@@ -522,7 +522,7 @@
 	int	h;
 
 	for (h = 0; h < MAX_HWIFS; h++) {
-		ide_hwif_t *hwif = &ide_hwifs[h];
+		struct ata_channel *hwif = &ide_hwifs[h];
 		int exist = (hwif->proc != NULL);
 #if 0
 		if (!hwif->present)
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 6cb6144..804c0f9 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -2058,7 +2058,7 @@
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
-		if (HWIF(drive)->dmaproc(ide_dma_end, drive)) {
+		if (drive->channel->dmaproc(ide_dma_end, drive)) {
 			/*
 			 * A DMA error is sometimes expected. For example,
 			 * if the tape is crossing a filemark during a
@@ -2132,7 +2132,7 @@
 	if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
 		printk (KERN_ERR "ide-tape: The tape wants to issue more interrupts in DMA mode\n");
 		printk (KERN_ERR "ide-tape: DMA disabled, reverting to PIO\n");
-		HWIF(drive)->dmaproc(ide_dma_off, drive);
+		drive->channel->dmaproc(ide_dma_off, drive);
 		return ide_stopped;
 	}
 #endif /* CONFIG_BLK_DEV_IDEDMA */
@@ -2155,7 +2155,8 @@
 			if (temp > pc->buffer_size) {
 				printk (KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n");
 				idetape_discard_data (drive, bcount.all);
-				ide_set_handler (drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
+				BUG_ON(HWGROUP(drive)->handler);
+				ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
 				return ide_started;
 			}
 #if IDETAPE_DEBUG_LOG
@@ -2181,7 +2182,8 @@
 	if (tape->debug_level >= 2)
 		printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes on that interrupt\n", pc->c[0], bcount.all);
 #endif
-	ide_set_handler (drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);	/* And set the interrupt handler again */
+	BUG_ON(HWGROUP(drive)->handler);
+	ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);	/* And set the interrupt handler again */
 	return ide_started;
 }
 
@@ -2255,6 +2257,7 @@
 		return ide_stopped;
 	}
 	tape->cmd_start_time = jiffies;
+	BUG_ON(HWGROUP(drive)->handler);
 	ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);	/* Set the interrupt routine */
 	atapi_output_bytes (drive,pc->c,12);			/* Send the actual packet */
 	return ide_started;
@@ -2309,10 +2312,10 @@
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) {
 		printk (KERN_WARNING "ide-tape: DMA disabled, reverting to PIO\n");
-		(void) HWIF(drive)->dmaproc(ide_dma_off, drive);
+		(void) drive->channel->dmaproc(ide_dma_off, drive);
 	}
 	if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
-		dma_ok = !HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
+		dma_ok = !drive->channel->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
 	if (IDE_CONTROL_REG)
@@ -2324,10 +2327,11 @@
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (dma_ok) {						/* Begin DMA, if necessary */
 		set_bit (PC_DMA_IN_PROGRESS, &pc->flags);
-		(void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
+		(void) drive->channel->dmaproc(ide_dma_begin, drive);
 	}
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 	if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
+		BUG_ON(HWGROUP(drive)->handler);
 		ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL);
 		OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG);
 		return ide_started;
@@ -3103,10 +3107,10 @@
 	idetape_tape_t *tape = drive->driver_data;
 	idetape_read_position_result_t *result;
 	
-//#if IDETAPE_DEBUG_LOG
-//	if (tape->debug_level >= 4)
+#if IDETAPE_DEBUG_LOG
+	if (tape->debug_level >= 4)
 		printk (KERN_INFO "ide-tape: Reached idetape_read_position_callback\n");
-//#endif /* IDETAPE_DEBUG_LOG */
+#endif /* IDETAPE_DEBUG_LOG */
 
 	if (!tape->pc->error) {
 		result = (idetape_read_position_result_t *) tape->pc->buffer;
@@ -3280,10 +3284,10 @@
 	idetape_pc_t pc;
 	int position;
 
-//#if IDETAPE_DEBUG_LOG
-//        if (tape->debug_level >= 4)
-	printk (KERN_INFO "ide-tape: Reached idetape_read_position\n");
-//#endif /* IDETAPE_DEBUG_LOG */
+#if IDETAPE_DEBUG_LOG
+	if (tape->debug_level >= 4)
+	    printk (KERN_INFO "ide-tape: Reached idetape_read_position\n");
+#endif /* IDETAPE_DEBUG_LOG */
 
 #ifdef NO_LONGER_REQUIRED
 	idetape_flush_tape_buffers(drive);
@@ -5997,13 +6001,13 @@
 		tape->onstream = 1;
 	drive->dsc_overlap = 1;
 #ifdef CONFIG_BLK_DEV_IDEPCI
-	if (!tape->onstream && HWIF(drive)->pci_dev != NULL) {
+	if (!tape->onstream && drive->channel->pci_dev != NULL) {
 		/*
 		 * These two ide-pci host adapters appear to need DSC overlap disabled.
 		 * This probably needs further analysis.
 		 */
-		if ((HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) ||
-		    (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_TTI_HPT343)) {
+		if ((drive->channel->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) ||
+		    (drive->channel->pci_dev->device == PCI_DEVICE_ID_TTI_HPT343)) {
 			printk(KERN_INFO "ide-tape: %s: disabling DSC overlap\n", tape->name);
 		    	drive->dsc_overlap = 0;
 		}
@@ -6099,8 +6103,7 @@
 	idetape_chrdevs[minor].drive = NULL;
 	restore_flags (flags);	/* all CPUs (overkill?) */
 
-	/* FIXME: this appears to be totally wrong! */
-	ata_ops(drive)->busy = 0;
+	MOD_DEC_USE_COUNT;
 
 	ide_unregister_subdriver (drive);
 	drive->driver_data = NULL;
@@ -6255,12 +6258,12 @@
 		idetape_chrdevs[minor].drive = drive;
 		tape->de_r =
 		    devfs_register (drive->de, "mt", DEVFS_FL_DEFAULT,
-				    HWIF(drive)->major, minor,
+				    drive->channel->major, minor,
 				    S_IFCHR | S_IRUGO | S_IWUGO,
 				    &idetape_fops, NULL);
 		tape->de_n =
 		    devfs_register (drive->de, "mtn", DEVFS_FL_DEFAULT,
-				    HWIF(drive)->major, minor + 128,
+				    drive->channel->major, minor + 128,
 				    S_IFCHR | S_IRUGO | S_IWUGO,
 				    &idetape_fops, NULL);
 		devfs_register_tape (tape->de_r);
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 29ccab9..33a3367 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -33,7 +33,7 @@
 #define DEBUG_TASKFILE	0	/* unset when fixed */
 
 #if DEBUG_TASKFILE
-#define DTF(x...) printk(##x)
+#define DTF(x...) printk(x)
 #else
 #define DTF(x...)
 #endif
@@ -48,14 +48,14 @@
 	if (rq->bio)
 		return bio_kmap_irq(rq->bio, flags) + ide_rq_offset(rq);
 	else
-		return rq->buffer + task_rq_offset(rq);
+		return rq->buffer + ((rq)->nr_sectors - (rq)->current_nr_sectors) * SECTOR_SIZE;
 }
 
 static inline void ide_unmap_rq(struct request *rq, char *to,
 				unsigned long *flags)
 {
 	if (rq->bio)
-	    bio_kunmap_irq(to, flags);
+		bio_kunmap_irq(to, flags);
 }
 
 static void bswap_data (void *buffer, int wcount)
@@ -98,8 +98,8 @@
 	 * for handling polled ide transfers
 	 */
 
-	if (HWIF(drive)->ideproc) {
-		HWIF(drive)->ideproc(ideproc_ide_input_data, drive, buffer, wcount);
+	if (drive->channel->ideproc) {
+		drive->channel->ideproc(ideproc_ide_input_data, drive, buffer, wcount);
 		return;
 	}
 
@@ -138,8 +138,8 @@
 {
 	byte io_32bit;
 
-	if (HWIF(drive)->ideproc) {
-		HWIF(drive)->ideproc(ideproc_ide_output_data, drive, buffer, wcount);
+	if (drive->channel->ideproc) {
+		drive->channel->ideproc(ideproc_ide_output_data, drive, buffer, wcount);
 		return;
 	}
 
@@ -180,8 +180,8 @@
  */
 void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount)
 {
-	if (HWIF(drive)->ideproc) {
-		HWIF(drive)->ideproc(ideproc_atapi_input_bytes, drive, buffer, bytecount);
+	if (drive->channel->ideproc) {
+		drive->channel->ideproc(ideproc_atapi_input_bytes, drive, buffer, bytecount);
 		return;
 	}
 
@@ -200,8 +200,8 @@
 
 void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount)
 {
-	if (HWIF(drive)->ideproc) {
-		HWIF(drive)->ideproc(ideproc_atapi_output_bytes, drive, buffer, bytecount);
+	if (drive->channel->ideproc) {
+		drive->channel->ideproc(ideproc_atapi_output_bytes, drive, buffer, bytecount);
 		return;
 	}
 
@@ -243,7 +243,7 @@
 {
 	byte stat = 0;
 	if (drive->waiting_for_dma)
-		return HWIF(drive)->dmaproc(ide_dma_test_irq, drive);
+		return drive->channel->dmaproc(ide_dma_test_irq, drive);
 #if 0
 	/* need to guarantee 400ns since last command was issued */
 	udelay(1);
@@ -288,135 +288,124 @@
 			break;
 	}
 }
-static ide_startstop_t bio_mulout_intr(ide_drive_t *drive);
 
-/*
- * Handler for command write multiple
- * Called directly from execute_drive_cmd for the first bunch of sectors,
- * afterwards only by the ISR
- */
-static ide_startstop_t task_mulout_intr(ide_drive_t *drive)
+static ide_startstop_t pre_task_mulout_intr(ide_drive_t *drive, struct request *rq)
 {
-	unsigned int		msect, nsect;
+	ide_task_t *args = rq->special;
+	ide_startstop_t startstop;
+
+	/*
+	 * assign private copy for multi-write
+	 */
+	memcpy(&HWGROUP(drive)->wrq, rq, sizeof(struct request));
+
+	if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ))
+		return startstop;
+
+	ata_poll_drive_ready(drive);
+	return args->handler(drive);
+}
+
+static ide_startstop_t task_mulout_intr (ide_drive_t *drive)
+{
 	byte stat		= GET_STAT();
 	byte io_32bit		= drive->io_32bit;
-	struct request *rq	= HWGROUP(drive)->rq;
+	struct request *rq	= &HWGROUP(drive)->wrq;
 	ide_hwgroup_t *hwgroup	= HWGROUP(drive);
-	char *pBuf		= NULL;
-	unsigned long flags;
+	int mcount		= drive->mult_count;
+	ide_startstop_t startstop;
 
 	/*
 	 * (ks/hs): Handle last IRQ on multi-sector transfer,
 	 * occurs after all data was sent in this chunk
 	 */
-	if (rq->current_nr_sectors == 0) {
-		if (stat & (ERR_STAT|DRQ_STAT))
-			return ide_error(drive, "task_mulout_intr", stat);
+	if (!rq->nr_sectors) {
+		if (stat & (ERR_STAT|DRQ_STAT)) {
+			startstop = ide_error(drive, "task_mulout_intr", stat);
+			memcpy(rq, HWGROUP(drive)->rq, sizeof(struct request));
+			return startstop;
+		}
 
-		/*
-		 * there may be more, ide_do_request will restart it if
-		 * necessary
-		 */
-		ide_end_request(drive, 1);
+		__ide_end_request(drive, 1, rq->hard_nr_sectors);
+		rq->bio = NULL;
 
 		return ide_stopped;
 	}
 
-	if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) {
-		if (stat & (ERR_STAT|DRQ_STAT)) {
-			return ide_error(drive, "task_mulout_intr", stat);
+	if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
+		if (stat & (ERR_STAT | DRQ_STAT)) {
+			startstop = ide_error(drive, "task_mulout_intr", stat);
+			memcpy(rq, HWGROUP(drive)->rq, sizeof(struct request));
+			return startstop;
 		}
+
 		/* no data yet, so wait for another interrupt */
 		if (hwgroup->handler == NULL)
-			ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL);
+			ide_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL);
+
 		return ide_started;
 	}
 
-	/* (ks/hs): See task_mulin_intr */
-	msect = drive->mult_count;
-	nsect = rq->current_nr_sectors;
-	if (nsect > msect)
-		nsect = msect;
+	do {
+		char *buffer;
+		int nsect = rq->current_nr_sectors;
+		unsigned long flags;
 
-	pBuf = ide_map_rq(rq, &flags);
-	DTF("Multiwrite: %p, nsect: %d , rq->current_nr_sectors: %ld\n",
-		pBuf, nsect, rq->current_nr_sectors);
-	drive->io_32bit = 0;
-	taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS);
-	ide_unmap_rq(rq, pBuf, &flags);
+		if (nsect > mcount)
+			nsect = mcount;
+		mcount -= nsect;
+
+		buffer = bio_kmap_irq(rq->bio, &flags) + ide_rq_offset(rq);
+		rq->sector += nsect;
+		rq->nr_sectors -= nsect;
+		rq->current_nr_sectors -= nsect;
+
+		/* Do we move to the next bio after this? */
+		if (!rq->current_nr_sectors) {
+			/* remember to fix this up /jens */
+			struct bio *bio = rq->bio->bi_next;
+
+			/* end early if we ran out of requests */
+			if (!bio) {
+				mcount = 0;
+			} else {
+				rq->bio = bio;
+				rq->current_nr_sectors = bio_iovec(bio)->bv_len >> 9;
+			}
+		}
+
+		/*
+		 * Ok, we're all setup for the interrupt
+		 * re-entering us on the last transfer.
+		 */
+		taskfile_output_data(drive, buffer, nsect * SECTOR_WORDS);
+		bio_kunmap_irq(buffer, &flags);
+	} while (mcount);
+
 	drive->io_32bit = io_32bit;
 	rq->errors = 0;
-	/* Are we sure that this as all been already transfered? */
-	rq->current_nr_sectors -= nsect;
 	if (hwgroup->handler == NULL)
-		ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL);
+		ide_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL);
+
 	return ide_started;
 }
 
-ide_startstop_t do_rw_taskfile(ide_drive_t *drive, ide_task_t *task)
+ide_startstop_t ata_taskfile(ide_drive_t *drive,
+		struct hd_drive_task_hdr *taskfile,
+		struct hd_drive_hob_hdr *hobfile,
+		ide_handler_t *handler,
+		ide_pre_handler_t *prehandler,
+		struct request *rq
+		)
 {
-	task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
-	hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister;
 	struct hd_driveid *id = drive->id;
-	byte HIHI = (drive->addressing) ? 0xE0 : 0xEF;
+	u8 HIHI = (drive->addressing) ? 0xE0 : 0xEF;
 
 	/* (ks/hs): Moved to start, do not use for multiple out commands */
-	if (task->handler != task_mulout_intr && task->handler != bio_mulout_intr) {
+	if (handler != task_mulout_intr) {
 		if (IDE_CONTROL_REG)
 			OUT_BYTE(drive->ctl, IDE_CONTROL_REG);	/* clear nIEN */
-		SELECT_MASK(HWIF(drive), drive, 0);
-	}
-
-	if ((id->command_set_2 & 0x0400) &&
-	    (id->cfs_enable_2 & 0x0400) &&
-	    (drive->addressing == 1)) {
-		OUT_BYTE(hobfile->feature, IDE_FEATURE_REG);
-		OUT_BYTE(hobfile->sector_count, IDE_NSECTOR_REG);
-		OUT_BYTE(hobfile->sector_number, IDE_SECTOR_REG);
-		OUT_BYTE(hobfile->low_cylinder, IDE_LCYL_REG);
-		OUT_BYTE(hobfile->high_cylinder, IDE_HCYL_REG);
-	}
-
-	OUT_BYTE(taskfile->feature, IDE_FEATURE_REG);
-	OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG);
-	/* refers to number of sectors to transfer */
-	OUT_BYTE(taskfile->sector_number, IDE_SECTOR_REG);
-	/* refers to sector offset or start sector */
-	OUT_BYTE(taskfile->low_cylinder, IDE_LCYL_REG);
-	OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG);
-
-	OUT_BYTE((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG);
-	if (task->handler != NULL) {
-		ide_set_handler (drive, task->handler, WAIT_CMD, NULL);
-		OUT_BYTE(taskfile->command, IDE_COMMAND_REG);
-		/*
-		 * Warning check for race between handler and prehandler for
-		 * writing first block of data.  however since we are well
-		 * inside the boundaries of the seek, we should be okay.
-		 */
-		if (task->prehandler != NULL) {
-			return task->prehandler(drive, task->rq);
-		}
-	} else {
-		/* for dma commands we down set the handler */
-		if (drive->using_dma && !(HWIF(drive)->dmaproc(((taskfile->command == WIN_WRITEDMA) || (taskfile->command == WIN_WRITEDMA_EXT)) ? ide_dma_write : ide_dma_read, drive)));
-	}
-
-	return ide_started;
-}
-
-void do_taskfile(ide_drive_t *drive, struct hd_drive_task_hdr *taskfile,
-		struct hd_drive_hob_hdr *hobfile,
-		ide_handler_t *handler)
-{
-	struct hd_driveid *id = drive->id;
-	byte HIHI = (drive->addressing) ? 0xE0 : 0xEF;
-
-	/* (ks/hs): Moved to start, do not use for multiple out commands */
-	if (*handler != task_mulout_intr && handler != bio_mulout_intr) {
-		if (IDE_CONTROL_REG)
-			OUT_BYTE(drive->ctl, IDE_CONTROL_REG);  /* clear nIEN */
-		SELECT_MASK(HWIF(drive), drive, 0);
+		SELECT_MASK(drive->channel, drive, 0);
 	}
 
 	if ((id->command_set_2 & 0x0400) &&
@@ -439,12 +428,21 @@
 
 	OUT_BYTE((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG);
 	if (handler != NULL) {
-		ide_set_handler (drive, handler, WAIT_CMD, NULL);
+		ide_set_handler(drive, handler, WAIT_CMD, NULL);
 		OUT_BYTE(taskfile->command, IDE_COMMAND_REG);
+		/*
+		 * Warning check for race between handler and prehandler for
+		 * writing first block of data.  however since we are well
+		 * inside the boundaries of the seek, we should be okay.
+		 */
+		if (prehandler != NULL)
+			return prehandler(drive, rq);
 	} else {
 		/* for dma commands we down set the handler */
-		if (drive->using_dma && !(HWIF(drive)->dmaproc(((taskfile->command == WIN_WRITEDMA) || (taskfile->command == WIN_WRITEDMA_EXT)) ? ide_dma_write : ide_dma_read, drive)));
+		if (drive->using_dma && !(drive->channel->dmaproc(((taskfile->command == WIN_WRITEDMA) || (taskfile->command == WIN_WRITEDMA_EXT)) ? ide_dma_write : ide_dma_read, drive)));
 	}
+
+	return ide_started;
 }
 
 /*
@@ -567,8 +565,8 @@
 	}
 
 	/* (ks/hs): Fixed Multi Write */
-	if ((args->tfRegister[IDE_COMMAND_OFFSET] != WIN_MULTWRITE) &&
-	    (args->tfRegister[IDE_COMMAND_OFFSET] != WIN_MULTWRITE_EXT)) {
+	if ((args->taskfile.command != WIN_MULTWRITE) &&
+	    (args->taskfile.command != WIN_MULTWRITE_EXT)) {
 		unsigned long flags;
 		char *buf = ide_map_rq(rq, &flags);
 		/* For Write_sectors we need to stuff the first sector */
@@ -616,107 +614,6 @@
 	return ide_started;
 }
 
-static ide_startstop_t pre_bio_out_intr(ide_drive_t *drive, struct request *rq)
-{
-	ide_task_t *args = rq->special;
-	ide_startstop_t startstop;
-
-	/*
-	 * assign private copy for multi-write
-	 */
-	memcpy(&HWGROUP(drive)->wrq, rq, sizeof(struct request));
-
-	if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ))
-		return startstop;
-
-	ata_poll_drive_ready(drive);
-	return args->handler(drive);
-}
-
-
-static ide_startstop_t bio_mulout_intr (ide_drive_t *drive)
-{
-	byte stat		= GET_STAT();
-	byte io_32bit		= drive->io_32bit;
-	struct request *rq	= &HWGROUP(drive)->wrq;
-	ide_hwgroup_t *hwgroup	= HWGROUP(drive);
-	int mcount		= drive->mult_count;
-	ide_startstop_t startstop;
-
-	/*
-	 * (ks/hs): Handle last IRQ on multi-sector transfer,
-	 * occurs after all data was sent in this chunk
-	 */
-	if (!rq->nr_sectors) {
-		if (stat & (ERR_STAT|DRQ_STAT)) {
-			startstop = ide_error(drive, "bio_mulout_intr", stat);
-			memcpy(rq, HWGROUP(drive)->rq, sizeof(struct request));
-			return startstop;
-		}
-
-		__ide_end_request(drive, 1, rq->hard_nr_sectors);
-		HWGROUP(drive)->wrq.bio = NULL;
-		return ide_stopped;
-	}
-
-	if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
-		if (stat & (ERR_STAT | DRQ_STAT)) {
-			startstop = ide_error(drive, "bio_mulout_intr", stat);
-			memcpy(rq, HWGROUP(drive)->rq, sizeof(struct request));
-			return startstop;
-		}
-
-		/* no data yet, so wait for another interrupt */
-		if (hwgroup->handler == NULL)
-			ide_set_handler(drive, bio_mulout_intr, WAIT_CMD, NULL);
-
-		return ide_started;
-	}
-
-	do {
-		char *buffer;
-		int nsect = rq->current_nr_sectors;
-		unsigned long flags;
-
-		if (nsect > mcount)
-			nsect = mcount;
-		mcount -= nsect;
-
-		buffer = bio_kmap_irq(rq->bio, &flags) + ide_rq_offset(rq);
-		rq->sector += nsect;
-		rq->nr_sectors -= nsect;
-		rq->current_nr_sectors -= nsect;
-
-		/* Do we move to the next bio after this? */
-		if (!rq->current_nr_sectors) {
-			/* remember to fix this up /jens */
-			struct bio *bio = rq->bio->bi_next;
-
-			/* end early early we ran out of requests */
-			if (!bio) {
-				mcount = 0;
-			} else {
-				rq->bio = bio;
-				rq->current_nr_sectors = bio_iovec(bio)->bv_len >> 9;
-			}
-		}
-
-		/*
-		 * Ok, we're all setup for the interrupt
-		 * re-entering us on the last transfer.
-		 */
-		taskfile_output_data(drive, buffer, nsect * SECTOR_WORDS);
-		bio_kunmap_irq(buffer, &flags);
-	} while (mcount);
-
-	drive->io_32bit = io_32bit;
-	rq->errors = 0;
-	if (hwgroup->handler == NULL)
-		ide_set_handler(drive, bio_mulout_intr, WAIT_CMD, NULL);
-
-	return ide_started;
-}
-
 /*
  * Handler for command with Read Multiple
  */
@@ -774,12 +671,12 @@
 /* Called by ioctl to feature out type of command being called */
 void ide_cmd_type_parser(ide_task_t *args)
 {
-	struct hd_drive_task_hdr *taskfile = (struct hd_drive_task_hdr *) args->tfRegister;
+	struct hd_drive_task_hdr *taskfile = &args->taskfile;
 
 	args->prehandler = NULL;
 	args->handler = NULL;
 
-	switch(args->tfRegister[IDE_COMMAND_OFFSET]) {
+	switch(args->taskfile.command) {
 		case WIN_IDENTIFY:
 		case WIN_PIDENTIFY:
 			args->handler = task_in_intr;
@@ -814,8 +711,8 @@
 		case CFA_WRITE_MULTI_WO_ERASE:
 		case WIN_MULTWRITE:
 		case WIN_MULTWRITE_EXT:
-			args->prehandler = pre_bio_out_intr;
-			args->handler = bio_mulout_intr;
+			args->prehandler = pre_task_mulout_intr;
+			args->handler = task_mulout_intr;
 			args->command_type = IDE_DRIVE_TASK_RAW_WRITE;
 			return;
 
@@ -830,9 +727,11 @@
 		case WIN_SMART:
 			if (taskfile->feature == SMART_WRITE_LOG_SECTOR)
 				args->prehandler = pre_task_out_intr;
-			args->tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS;
-			args->tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS;
-			switch(args->tfRegister[IDE_FEATURE_OFFSET]) {
+
+			args->taskfile.low_cylinder = SMART_LCYL_PASS;
+			args->taskfile.high_cylinder = SMART_HCYL_PASS;
+
+			switch(args->taskfile.feature) {
 				case SMART_READ_VALUES:
 				case SMART_READ_THRESHOLDS:
 				case SMART_READ_LOG_SECTOR:
@@ -870,7 +769,7 @@
 #endif
 		case WIN_SETFEATURES:
 			args->handler = task_no_data_intr;
-			switch(args->tfRegister[IDE_FEATURE_OFFSET]) {
+			switch(args->taskfile.feature) {
 				case SETFEATURES_XFER:
 					args->command_type = IDE_DRIVE_TASK_SET_XFER;
 					return;
@@ -960,7 +859,7 @@
 /*
  * This function is intended to be used prior to invoking ide_do_drive_cmd().
  */
-static void ide_init_drive_taskfile (struct request *rq)
+static void init_taskfile_request(struct request *rq)
 {
 	memset(rq, 0, sizeof(*rq));
 	rq->flags = REQ_DRIVE_TASKFILE;
@@ -968,37 +867,25 @@
 
 /*
  * This is kept for internal use only !!!
- * This is an internal call and nobody in user-space has a damn
+ * This is an internal call and nobody in user-space has a
  * reason to call this taskfile.
  *
  * ide_raw_taskfile is the one that user-space executes.
  */
+
 int ide_wait_taskfile(ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile, byte *buf)
 {
 	struct request rq;
+	/* FIXME: This is on stack! */
 	ide_task_t args;
 
 	memset(&args, 0, sizeof(ide_task_t));
 
-	args.tfRegister[IDE_DATA_OFFSET]         = taskfile->data;
-	args.tfRegister[IDE_FEATURE_OFFSET]      = taskfile->feature;
-	args.tfRegister[IDE_NSECTOR_OFFSET]      = taskfile->sector_count;
-	args.tfRegister[IDE_SECTOR_OFFSET]       = taskfile->sector_number;
-	args.tfRegister[IDE_LCYL_OFFSET]         = taskfile->low_cylinder;
-	args.tfRegister[IDE_HCYL_OFFSET]         = taskfile->high_cylinder;
-	args.tfRegister[IDE_SELECT_OFFSET]       = taskfile->device_head;
-	args.tfRegister[IDE_COMMAND_OFFSET]      = taskfile->command;
+	args.taskfile = *taskfile;
+	args.hobfile = *hobfile;
 
-	args.hobRegister[IDE_DATA_OFFSET_HOB]    = hobfile->data;
-	args.hobRegister[IDE_FEATURE_OFFSET_HOB] = hobfile->feature;
-	args.hobRegister[IDE_NSECTOR_OFFSET_HOB] = hobfile->sector_count;
-	args.hobRegister[IDE_SECTOR_OFFSET_HOB]  = hobfile->sector_number;
-	args.hobRegister[IDE_LCYL_OFFSET_HOB]    = hobfile->low_cylinder;
-	args.hobRegister[IDE_HCYL_OFFSET_HOB]    = hobfile->high_cylinder;
-	args.hobRegister[IDE_SELECT_OFFSET_HOB]  = hobfile->device_head;
-	args.hobRegister[IDE_CONTROL_OFFSET_HOB] = hobfile->control;
+	init_taskfile_request(&rq);
 
-	ide_init_drive_taskfile(&rq);
 	/* This is kept for internal use only !!! */
 	ide_cmd_type_parser(&args);
 	if (args.command_type != IDE_DRIVE_TASK_NO_DATA)
@@ -1006,64 +893,33 @@
 
 	rq.buffer = buf;
 	rq.special = &args;
+
 	return ide_do_drive_cmd(drive, &rq, ide_wait);
 }
 
 int ide_raw_taskfile(ide_drive_t *drive, ide_task_t *args, byte *buf)
 {
 	struct request rq;
-	ide_init_drive_taskfile(&rq);
+	init_taskfile_request(&rq);
 	rq.buffer = buf;
 
 	if (args->command_type != IDE_DRIVE_TASK_NO_DATA)
-		rq.current_nr_sectors = rq.nr_sectors = (args->hobRegister[IDE_NSECTOR_OFFSET_HOB] << 8) | args->tfRegister[IDE_NSECTOR_OFFSET];
+		rq.current_nr_sectors = rq.nr_sectors
+			= (args->hobfile.sector_count << 8)
+			| args->taskfile.sector_count;
 
 	rq.special = args;
+
 	return ide_do_drive_cmd(drive, &rq, ide_wait);
 }
 
 /*
- *  The taskfile glue table
- *
- *  reqtask.data_phase	reqtask.req_cmd
- *			args.command_type		args.handler
- *
- *  TASKFILE_P_OUT_DMAQ	??				??
- *  TASKFILE_P_IN_DMAQ	??				??
- *  TASKFILE_P_OUT_DMA	??				??
- *  TASKFILE_P_IN_DMA	??				??
- *  TASKFILE_P_OUT	??				??
- *  TASKFILE_P_IN	??				??
- *
- *  TASKFILE_OUT_DMAQ	IDE_DRIVE_TASK_RAW_WRITE	NULL
- *  TASKFILE_IN_DMAQ	IDE_DRIVE_TASK_IN		NULL
- *
- *  TASKFILE_OUT_DMA	IDE_DRIVE_TASK_RAW_WRITE	NULL
- *  TASKFILE_IN_DMA	IDE_DRIVE_TASK_IN		NULL
- *
- *  TASKFILE_IN_OUT	??				??
- *
- *  TASKFILE_MULTI_OUT	IDE_DRIVE_TASK_RAW_WRITE	task_mulout_intr
- *  TASKFILE_MULTI_IN	IDE_DRIVE_TASK_IN		task_mulin_intr
- *
- *  TASKFILE_OUT	IDE_DRIVE_TASK_RAW_WRITE	task_out_intr
- *  TASKFILE_OUT	IDE_DRIVE_TASK_OUT		task_out_intr
- *
- *  TASKFILE_IN		IDE_DRIVE_TASK_IN		task_in_intr
- *  TASKFILE_NO_DATA	IDE_DRIVE_TASK_NO_DATA		task_no_data_intr
- *
- *			IDE_DRIVE_TASK_SET_XFER		task_no_data_intr
- *			IDE_DRIVE_TASK_INVALID
- *
- */
-
-/*
- * Issue ATA command and wait for completion. use for implementing commands in
+ * Issue ATA command and wait for completion. Use for implementing commands in
  * kernel.
  *
  * The caller has to make sure buf is never NULL!
  */
-static int ide_wait_cmd(ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *argbuf)
+static int ide_wait_cmd(ide_drive_t *drive, u8 cmd, u8 nsect, u8 feature, u8 sectors, u8 *argbuf)
 {
 	struct request rq;
 
@@ -1072,10 +928,10 @@
 	memset(argbuf, 0, 4 + SECTOR_WORDS * 4 * sectors);
 	ide_init_drive_cmd(&rq);
 	rq.buffer = argbuf;
-	*argbuf++ = cmd;
-	*argbuf++ = nsect;
-	*argbuf++ = feature;
-	*argbuf++ = sectors;
+	argbuf[0] = cmd;
+	argbuf[1] = nsect;
+	argbuf[2] = feature;
+	argbuf[3] = sectors;
 
 	return ide_do_drive_cmd(drive, &rq, ide_wait);
 }
@@ -1083,7 +939,8 @@
 int ide_cmd_ioctl(ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
 	int err = 0;
-	byte args[4], *argbuf = args;
+	u8 args[4];
+	u8 *argbuf = args;
 	byte xfer_rate = 0;
 	int argsize = 4;
 	ide_task_t tfargs;
@@ -1096,13 +953,13 @@
 	if (copy_from_user(args, (void *)arg, 4))
 		return -EFAULT;
 
-	tfargs.tfRegister[IDE_FEATURE_OFFSET] = args[2];
-	tfargs.tfRegister[IDE_NSECTOR_OFFSET] = args[3];
-	tfargs.tfRegister[IDE_SECTOR_OFFSET]  = args[1];
-	tfargs.tfRegister[IDE_LCYL_OFFSET]    = 0x00;
-	tfargs.tfRegister[IDE_HCYL_OFFSET]    = 0x00;
-	tfargs.tfRegister[IDE_SELECT_OFFSET]  = 0x00;
-	tfargs.tfRegister[IDE_COMMAND_OFFSET] = args[0];
+	tfargs.taskfile.feature = args[2];
+	tfargs.taskfile.sector_count = args[3];
+	tfargs.taskfile.sector_number = args[1];
+	tfargs.taskfile.low_cylinder = 0x00;
+	tfargs.taskfile.high_cylinder = 0x00;
+	tfargs.taskfile.device_head = 0x00;
+	tfargs.taskfile.command = args[0];
 
 	if (args[3]) {
 		argsize = 4 + (SECTOR_WORDS * 4 * args[3]);
@@ -1121,8 +978,8 @@
 
 	if (!err && xfer_rate) {
 		/* active-retuning-calls future */
-		if ((HWIF(drive)->speedproc) != NULL)
-			HWIF(drive)->speedproc(drive, xfer_rate);
+		if ((drive->channel->speedproc) != NULL)
+			drive->channel->speedproc(drive, xfer_rate);
 		ide_driveid_update(drive);
 	}
 abort:
@@ -1162,8 +1019,7 @@
 EXPORT_SYMBOL(atapi_output_bytes);
 EXPORT_SYMBOL(taskfile_input_data);
 EXPORT_SYMBOL(taskfile_output_data);
-EXPORT_SYMBOL(do_rw_taskfile);
-EXPORT_SYMBOL(do_taskfile);
+EXPORT_SYMBOL(ata_taskfile);
 
 EXPORT_SYMBOL(recal_intr);
 EXPORT_SYMBOL(set_geometry_intr);
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 6cf6d4e..75f0f19 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -223,7 +223,7 @@
 /*
  * This is declared extern in ide.h, for access by other IDE modules:
  */
-ide_hwif_t ide_hwifs[MAX_HWIFS];	/* master data repository */
+struct ata_channel ide_hwifs[MAX_HWIFS];	/* master data repository */
 
 #if (DISK_RECOVERY_TIME > 0)
 /*
@@ -244,19 +244,19 @@
 	__restore_flags(flags);	/* local CPU only */
 	return (t - i);
 }
-#endif /* DISK_RECOVERY_TIME */
+#endif
 
-static inline void set_recovery_timer (ide_hwif_t *hwif)
+static inline void set_recovery_timer(struct ata_channel *channel)
 {
 #if (DISK_RECOVERY_TIME > 0)
-	hwif->last_time = read_timer();
-#endif /* DISK_RECOVERY_TIME */
+	channel->last_time = read_timer();
+#endif
 }
 
 /*
  * Do not even *think* about calling this!
  */
-static void init_hwif_data(ide_hwif_t *hwif, unsigned int index)
+static void init_hwif_data(struct ata_channel *hwif, unsigned int index)
 {
 	static const byte ide_major[] = {
 		IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR,
@@ -267,7 +267,7 @@
 	hw_regs_t hw;
 
 	/* bulk initialize hwif & drive info with zeros */
-	memset(hwif, 0, sizeof(ide_hwif_t));
+	memset(hwif, 0, sizeof(struct ata_channel));
 	memset(&hw, 0, sizeof(hw_regs_t));
 
 	/* fill in any non-zero initial values */
@@ -288,7 +288,7 @@
 
 		drive->type			= ATA_DISK;
 		drive->select.all		= (unit<<4)|0xa0;
-		drive->hwif			= hwif;
+		drive->channel			= hwif;
 		drive->ctl			= 0x08;
 		drive->ready_stat		= READY_STAT;
 		drive->bad_wstat		= BAD_W_STAT;
@@ -445,13 +445,13 @@
 	if (drive->using_dma) {
 		/* check the DMA crc count */
 		if (drive->crc_count) {
-			HWIF(drive)->dmaproc(ide_dma_off_quietly, drive);
-			if ((HWIF(drive)->speedproc) != NULL)
-				HWIF(drive)->speedproc(drive, ide_auto_reduce_xfer(drive));
+			drive->channel->dmaproc(ide_dma_off_quietly, drive);
+			if ((drive->channel->speedproc) != NULL)
+				drive->channel->speedproc(drive, ide_auto_reduce_xfer(drive));
 			if (drive->current_speed >= XFER_SW_DMA_0)
-				HWIF(drive)->dmaproc(ide_dma_on, drive);
+				drive->channel->dmaproc(ide_dma_on, drive);
 		} else
-			HWIF(drive)->dmaproc(ide_dma_off, drive);
+			drive->channel->dmaproc(ide_dma_off, drive);
 	}
 }
 
@@ -483,7 +483,7 @@
 	printk("%s: ata_special: 0x%02x\n", drive->name, s->all);
 #endif
 	if (s->b.set_tune) {
-		ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc;
+		ide_tuneproc_t *tuneproc = drive->channel->tuneproc;
 		s->b.set_tune = 0;
 		if (tuneproc != NULL)
 			tuneproc(drive, drive->tune_req);
@@ -507,9 +507,9 @@
 extern struct block_device_operations ide_fops[];
 
 /*
- * ide_geninit() is called exactly *once* for each interface.
+ * This is called exactly *once* for each channel.
  */
-void ide_geninit (ide_hwif_t *hwif)
+void ide_geninit(struct ata_channel *hwif)
 {
 	unsigned int unit;
 	struct gendisk *gd = hwif->gd;
@@ -542,13 +542,14 @@
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
 	byte stat;
 
-	SELECT_DRIVE(HWIF(drive),drive);
+	SELECT_DRIVE(drive->channel,drive);
 	udelay (10);
 
 	if (OK_STAT(stat=GET_STAT(), 0, BUSY_STAT)) {
 		printk("%s: ATAPI reset complete\n", drive->name);
 	} else {
-		if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) {
+		if (time_before(jiffies, hwgroup->poll_timeout)) {
+			BUG_ON(HWGROUP(drive)->handler);
 			ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL);
 			return ide_started;	/* continue polling */
 		}
@@ -569,11 +570,12 @@
 static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
 {
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	byte tmp;
 
 	if (!OK_STAT(tmp=GET_STAT(), 0, BUSY_STAT)) {
-		if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) {
+		if (time_before(jiffies, hwgroup->poll_timeout)) {
+			BUG_ON(HWGROUP(drive)->handler);
 			ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL);
 			return ide_started;	/* continue polling */
 		}
@@ -632,7 +634,7 @@
 {
 	unsigned int unit;
 	unsigned long flags;
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
 
 	__save_flags(flags);	/* local CPU only */
@@ -645,6 +647,7 @@
 		udelay (20);
 		OUT_BYTE (WIN_SRST, IDE_COMMAND_REG);
 		hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
+		BUG_ON(HWGROUP(drive)->handler);
 		ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL);
 		__restore_flags (flags);	/* local CPU only */
 		return ide_started;
@@ -679,7 +682,8 @@
 	}
 	udelay(10);			/* more than enough time */
 	hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
-	ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL);
+	BUG_ON(HWGROUP(drive)->handler);
+	ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
 
 	/*
 	 * Some weird controller like resetting themselves to a strange
@@ -737,27 +741,25 @@
 		ide_task_t *args = (ide_task_t *) rq->special;
 		rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
 		if (args) {
-			if (args->tf_in_flags.b.data) {
-				unsigned short data			= IN_WORD(IDE_DATA_REG);
-				args->tfRegister[IDE_DATA_OFFSET]	= (data) & 0xFF;
-				args->hobRegister[IDE_DATA_OFFSET_HOB]	= (data >> 8) & 0xFF;
-			}
-			args->tfRegister[IDE_ERROR_OFFSET]   = err;
-			args->tfRegister[IDE_NSECTOR_OFFSET] = IN_BYTE(IDE_NSECTOR_REG);
-			args->tfRegister[IDE_SECTOR_OFFSET]  = IN_BYTE(IDE_SECTOR_REG);
-			args->tfRegister[IDE_LCYL_OFFSET]    = IN_BYTE(IDE_LCYL_REG);
-			args->tfRegister[IDE_HCYL_OFFSET]    = IN_BYTE(IDE_HCYL_REG);
-			args->tfRegister[IDE_SELECT_OFFSET]  = IN_BYTE(IDE_SELECT_REG);
-			args->tfRegister[IDE_STATUS_OFFSET]  = stat;
+			args->taskfile.feature = err;
+			args->taskfile.sector_count = IN_BYTE(IDE_NSECTOR_REG);
+			args->taskfile.sector_number = IN_BYTE(IDE_SECTOR_REG);
+			args->taskfile.low_cylinder = IN_BYTE(IDE_LCYL_REG);
+			args->taskfile.high_cylinder = IN_BYTE(IDE_HCYL_REG);
+			args->taskfile.device_head = IN_BYTE(IDE_SELECT_REG);
+			args->taskfile.command = stat;
 			if ((drive->id->command_set_2 & 0x0400) &&
 			    (drive->id->cfs_enable_2 & 0x0400) &&
 			    (drive->addressing == 1)) {
-				OUT_BYTE(drive->ctl|0x80, IDE_CONTROL_REG_HOB);
-				args->hobRegister[IDE_FEATURE_OFFSET_HOB] = IN_BYTE(IDE_FEATURE_REG);
-				args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = IN_BYTE(IDE_NSECTOR_REG);
-				args->hobRegister[IDE_SECTOR_OFFSET_HOB]  = IN_BYTE(IDE_SECTOR_REG);
-				args->hobRegister[IDE_LCYL_OFFSET_HOB]    = IN_BYTE(IDE_LCYL_REG);
-				args->hobRegister[IDE_HCYL_OFFSET_HOB]    = IN_BYTE(IDE_HCYL_REG);
+				/* The following command goes to the hob file! */
+
+				OUT_BYTE(drive->ctl|0x80, IDE_CONTROL_REG);
+				args->hobfile.feature = IN_BYTE(IDE_FEATURE_REG);
+				args->hobfile.sector_count = IN_BYTE(IDE_NSECTOR_REG);
+
+				args->hobfile.sector_number = IN_BYTE(IDE_SECTOR_REG);
+				args->hobfile.low_cylinder = IN_BYTE(IDE_LCYL_REG);
+				args->hobfile.high_cylinder = IN_BYTE(IDE_HCYL_REG);
 			}
 		}
 	}
@@ -933,10 +935,11 @@
  */
 void ide_cmd (ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler)
 {
+	BUG_ON(HWGROUP(drive)->handler);
 	ide_set_handler (drive, handler, WAIT_CMD, NULL);
 	if (IDE_CONTROL_REG)
 		OUT_BYTE(drive->ctl,IDE_CONTROL_REG);	/* clear nIEN */
-	SELECT_MASK(HWIF(drive),drive,0);
+	SELECT_MASK(drive->channel, drive, 0);
 	OUT_BYTE(nsect,IDE_NSECTOR_REG);
 	OUT_BYTE(cmd,IDE_COMMAND_REG);
 }
@@ -978,7 +981,7 @@
  * setting a timer to wake up at half second intervals thereafter,
  * until timeout is achieved, before timing out.
  */
-int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, byte good, byte bad, unsigned long timeout) {
+int ide_wait_stat(ide_startstop_t *startstop, ide_drive_t *drive, byte good, byte bad, unsigned long timeout) {
 	byte stat;
 	int i;
 	unsigned long flags;
@@ -1020,90 +1023,6 @@
 }
 
 /*
- * execute_drive_cmd() issues a special drive command,
- * usually initiated by ioctl() from the external hdparm program.
- */
-static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq)
-{
-	if (rq->flags & REQ_DRIVE_TASKFILE) {
-		ide_task_t *args = rq->special;
-
-		if (!(args))
-			goto args_error;
-
-		do_taskfile(drive,
-				(struct hd_drive_task_hdr *)&args->tfRegister,
-				(struct hd_drive_hob_hdr *)&args->hobRegister,
-				args->handler);
-
-		if (((args->command_type == IDE_DRIVE_TASK_RAW_WRITE) ||
-		     (args->command_type == IDE_DRIVE_TASK_OUT)) &&
-		      args->prehandler && args->handler)
-			return args->prehandler(drive, rq);
-		return ide_started;
-
-	} else if (rq->flags & REQ_DRIVE_TASK) {
-		byte *args = rq->buffer;
-		byte sel;
-
-		if (!(args)) goto args_error;
-#ifdef DEBUG
-			printk("%s: DRIVE_TASK_CMD ", drive->name);
-			printk("cmd=0x%02x ", args[0]);
-			printk("fr=0x%02x ", args[1]);
-			printk("ns=0x%02x ", args[2]);
-			printk("sc=0x%02x ", args[3]);
-			printk("lcyl=0x%02x ", args[4]);
-			printk("hcyl=0x%02x ", args[5]);
-			printk("sel=0x%02x\n", args[6]);
-#endif
-		OUT_BYTE(args[1], IDE_FEATURE_REG);
-		OUT_BYTE(args[3], IDE_SECTOR_REG);
-		OUT_BYTE(args[4], IDE_LCYL_REG);
-		OUT_BYTE(args[5], IDE_HCYL_REG);
-		sel = (args[6] & ~0x10);
-		if (drive->select.b.unit)
-			sel |= 0x10;
-		OUT_BYTE(sel, IDE_SELECT_REG);
-		ide_cmd(drive, args[0], args[2], &drive_cmd_intr);
-		return ide_started;
-	} else if (rq->flags & REQ_DRIVE_CMD) {
-
-		byte *args = rq->buffer;
-		if (!(args)) goto args_error;
-#ifdef DEBUG
-		printk("%s: DRIVE_CMD ", drive->name);
-		printk("cmd=0x%02x ", args[0]);
-		printk("sc=0x%02x ", args[1]);
-		printk("fr=0x%02x ", args[2]);
-		printk("xx=0x%02x\n", args[3]);
-#endif
-		if (args[0] == WIN_SMART) {
-			OUT_BYTE(0x4f, IDE_LCYL_REG);
-			OUT_BYTE(0xc2, IDE_HCYL_REG);
-			OUT_BYTE(args[2],IDE_FEATURE_REG);
-			OUT_BYTE(args[1],IDE_SECTOR_REG);
-			ide_cmd(drive, args[0], args[3], &drive_cmd_intr);
-			return ide_started;
-		}
-		OUT_BYTE(args[2],IDE_FEATURE_REG);
-		ide_cmd(drive, args[0], args[1], &drive_cmd_intr);
-		return ide_started;
-	}
-
-args_error:
-	/*
-	 * NULL is actually a valid way of waiting for
-	 * all current requests to be flushed from the queue.
-	 */
-#ifdef DEBUG
-	printk("%s: DRIVE_CMD (null)\n", drive->name);
-#endif
-	ide_end_drive_cmd(drive, GET_STAT(), GET_ERR());
-	return ide_stopped;
-}
-
-/*
  * start_request() initiates handling of a new I/O request
  */
 static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
@@ -1111,7 +1030,7 @@
 	ide_startstop_t startstop;
 	unsigned long block;
 	unsigned int minor = minor(rq->rq_dev), unit = minor >> PARTN_BITS;
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 
 	BUG_ON(!(rq->flags & REQ_STARTED));
 
@@ -1150,9 +1069,100 @@
 		printk(KERN_WARNING "%s: drive not ready for command\n", drive->name);
 		return startstop;
 	}
+
+	/* FIXME: We can see nicely here that all commands should be submitted
+	 * through the request queue and that the special field in drive should
+	 * go as soon as possible!
+	 */
+
 	if (!drive->special.all) {
-		if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE))
-			return execute_drive_cmd(drive, rq);
+		if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {
+			/* This issues a special drive command, usually
+			 * initiated by ioctl() from the external hdparm
+			 * program.
+			 */
+
+			if (rq->flags & REQ_DRIVE_TASKFILE) {
+				ide_task_t *args = rq->special;
+
+				if (!(args))
+					goto args_error;
+
+				ata_taskfile(drive,
+						&args->taskfile,
+						&args->hobfile,
+						args->handler, NULL, NULL);
+
+				if (((args->command_type == IDE_DRIVE_TASK_RAW_WRITE) ||
+					(args->command_type == IDE_DRIVE_TASK_OUT)) &&
+						args->prehandler && args->handler)
+					return args->prehandler(drive, rq);
+				return ide_started;
+
+			} else if (rq->flags & REQ_DRIVE_TASK) {
+				byte *args = rq->buffer;
+				byte sel;
+
+				if (!(args)) goto args_error;
+#ifdef DEBUG
+				printk("%s: DRIVE_TASK_CMD ", drive->name);
+				printk("cmd=0x%02x ", args[0]);
+				printk("fr=0x%02x ", args[1]);
+				printk("ns=0x%02x ", args[2]);
+				printk("sc=0x%02x ", args[3]);
+				printk("lcyl=0x%02x ", args[4]);
+				printk("hcyl=0x%02x ", args[5]);
+				printk("sel=0x%02x\n", args[6]);
+#endif
+				OUT_BYTE(args[1], IDE_FEATURE_REG);
+				OUT_BYTE(args[3], IDE_SECTOR_REG);
+				OUT_BYTE(args[4], IDE_LCYL_REG);
+				OUT_BYTE(args[5], IDE_HCYL_REG);
+				sel = (args[6] & ~0x10);
+				if (drive->select.b.unit)
+					sel |= 0x10;
+				OUT_BYTE(sel, IDE_SELECT_REG);
+				ide_cmd(drive, args[0], args[2], &drive_cmd_intr);
+				return ide_started;
+			} else if (rq->flags & REQ_DRIVE_CMD) {
+				byte *args = rq->buffer;
+				if (!(args)) goto args_error;
+#ifdef DEBUG
+				printk("%s: DRIVE_CMD ", drive->name);
+				printk("cmd=0x%02x ", args[0]);
+				printk("sc=0x%02x ", args[1]);
+				printk("fr=0x%02x ", args[2]);
+				printk("xx=0x%02x\n", args[3]);
+#endif
+				if (args[0] == WIN_SMART) {
+					OUT_BYTE(0x4f, IDE_LCYL_REG);
+					OUT_BYTE(0xc2, IDE_HCYL_REG);
+					OUT_BYTE(args[2],IDE_FEATURE_REG);
+					OUT_BYTE(args[1],IDE_SECTOR_REG);
+					ide_cmd(drive, args[0], args[3], &drive_cmd_intr);
+
+					return ide_started;
+				}
+				OUT_BYTE(args[2],IDE_FEATURE_REG);
+				ide_cmd(drive, args[0], args[1], &drive_cmd_intr);
+				return ide_started;
+			}
+
+args_error:
+			/*
+			 * NULL is actually a valid way of waiting for all
+			 * current requests to be flushed from the queue.
+			 */
+#ifdef DEBUG
+			printk("%s: DRIVE_CMD (null)\n", drive->name);
+#endif
+			ide_end_drive_cmd(drive, GET_STAT(), GET_ERR());
+			return ide_stopped;
+		}
+
+		/* The normal way of execution is to pass execute the request
+		 * handler.
+		 */
 
 		if (ata_ops(drive)) {
 			if (ata_ops(drive)->do_request)
@@ -1194,55 +1204,34 @@
  * 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)
+void ide_stall_queue(ide_drive_t *drive, unsigned long timeout)
 {
 	if (timeout > WAIT_WORSTCASE)
 		timeout = WAIT_WORSTCASE;
-	drive->sleep = timeout + jiffies;
+	drive->PADAM_sleep = timeout + jiffies;
 }
 
-#define WAKEUP(drive)	((drive)->service_start + 2 * (drive)->service_time)
-
 /*
  * choose_drive() selects the next drive which will be serviced.
  */
-static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup)
+static inline ide_drive_t *choose_drive(ide_hwgroup_t *hwgroup)
 {
 	ide_drive_t *drive, *best;
 
-repeat:
 	best = NULL;
 	drive = hwgroup->drive;
 	do {
-		if (!list_empty(&drive->queue.queue_head) && (!drive->sleep || 0 <= (signed long)(jiffies - drive->sleep))) {
+		if (!list_empty(&drive->queue.queue_head)
+		&& (!drive->PADAM_sleep	|| time_after_eq(drive->PADAM_sleep, jiffies))) {
 			if (!best
-			 || (drive->sleep && (!best->sleep || 0 < (signed long)(best->sleep - drive->sleep)))
-			 || (!best->sleep && 0 < (signed long)(WAKEUP(best) - WAKEUP(drive))))
+			 || (drive->PADAM_sleep && (!best->PADAM_sleep || time_after(best->PADAM_sleep, drive->PADAM_sleep)))
+			 || (!best->PADAM_sleep && time_after(best->PADAM_service_start + 2 * best->PADAM_service_time, drive->PADAM_service_start + 2 * drive->PADAM_service_time)))
 			{
 				if (!blk_queue_plugged(&drive->queue))
 					best = drive;
 			}
 		}
 	} while ((drive = drive->next) != hwgroup->drive);
-	if (best && best->nice1 && !best->sleep && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) {
-		long t = (signed long)(WAKEUP(best) - jiffies);
-		if (t >= WAIT_MIN_SLEEP) {
-			/*
-			 * We *may* have some time to spare, but first let's see if
-			 * someone can potentially benefit from our nice mood today..
-			 */
-			drive = best->next;
-			do {
-				if (!drive->sleep
-				 && 0 < (signed long)(WAKEUP(drive) - (jiffies - best->service_time))
-				 && 0 < (signed long)((jiffies + t) - WAKEUP(drive)))
-				{
-					ide_stall_queue(best, min(t, 10L * WAIT_MIN_SLEEP));
-					goto repeat;
-				}
-			} while ((drive = drive->next) != best);
-		}
-	}
 	return best;
 }
 
@@ -1278,8 +1267,8 @@
  */
 static void ide_do_request(ide_hwgroup_t *hwgroup, int masked_irq)
 {
-	ide_drive_t	*drive;
-	ide_hwif_t	*hwif;
+	ide_drive_t *drive;
+	struct ata_channel *hwif;
 	ide_startstop_t	startstop;
 	struct request	*rq;
 
@@ -1294,8 +1283,8 @@
 			hwgroup->rq = NULL;
 			drive = hwgroup->drive;
 			do {
-				if (drive->sleep && (!sleep || 0 < (signed long)(sleep - drive->sleep)))
-					sleep = drive->sleep;
+				if (drive->PADAM_sleep && (!sleep || time_after(sleep, drive->PADAM_sleep)))
+					sleep = drive->PADAM_sleep;
 			} while ((drive = drive->next) != hwgroup->drive);
 			if (sleep) {
 				/*
@@ -1304,7 +1293,7 @@
 				 * play fairly with us, just in case there are big differences
 				 * in relative throughputs.. don't want to hog the cpu too much.
 				 */
-				if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep)) 
+				if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep))
 					sleep = jiffies + WAIT_MIN_SLEEP;
 #if 1
 				if (timer_pending(&hwgroup->timer))
@@ -1320,7 +1309,7 @@
 			}
 			return;		/* no more work for this hwgroup (for now) */
 		}
-		hwif = HWIF(drive);
+		hwif = drive->channel;
 		if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif && hwif->io_ports[IDE_CONTROL_OFFSET]) {
 			/* set nIEN for previous hwif */
 
@@ -1331,8 +1320,8 @@
 		}
 		hwgroup->hwif = hwif;
 		hwgroup->drive = drive;
-		drive->sleep = 0;
-		drive->service_start = jiffies;
+		drive->PADAM_sleep = 0;
+		drive->PADAM_service_start = jiffies;
 
 		if (blk_queue_plugged(&drive->queue))
 			BUG();
@@ -1366,11 +1355,12 @@
 /*
  * Returns the queue which corresponds to a given device.
  */
-request_queue_t *ide_get_queue (kdev_t dev)
+request_queue_t *ide_get_queue(kdev_t dev)
 {
-	ide_hwif_t *hwif = (ide_hwif_t *)blk_dev[major(dev)].data;
+	struct ata_channel *channel = (struct ata_channel *)blk_dev[major(dev)].data;
 
-	return &hwif->drives[DEVICE_NR(dev) & 1].queue;
+	/* FIXME: ALLERT: This discriminates between master and slave! */
+	return &channel->drives[DEVICE_NR(dev) & 1].queue;
 }
 
 /*
@@ -1388,7 +1378,7 @@
  */
 void ide_dma_timeout_retry(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct request *rq;
 
 	/*
@@ -1461,7 +1451,7 @@
 			printk("ide_timer_expiry: hwgroup->drive was NULL\n");
 			hwgroup->handler = NULL;
 		} else {
-			ide_hwif_t *hwif;
+			struct ata_channel *hwif;
 			ide_startstop_t startstop;
 			/* paranoia */
 			if (!test_and_set_bit(IDE_BUSY, &hwgroup->flags))
@@ -1483,7 +1473,7 @@
 			 * mask the specific IRQ:
 			 */
 			spin_unlock(&ide_lock);
-			hwif  = HWIF(drive);
+			hwif  = drive->channel;
 #if DISABLE_IRQ_NOSYNC
 			disable_irq_nosync(hwif->irq);
 #else
@@ -1506,7 +1496,7 @@
 					startstop = ide_error(drive, "irq timeout", GET_STAT());
 			}
 			set_recovery_timer(hwif);
-			drive->service_time = jiffies - drive->service_start;
+			drive->PADAM_service_time = jiffies - drive->PADAM_service_start;
 			enable_irq(hwif->irq);
 			spin_lock_irq(&ide_lock);
 			if (startstop == ide_stopped)
@@ -1540,10 +1530,10 @@
  * accidentally invoked as a result of any valid command completion interrupt.
  *
  */
-static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
+static void unexpected_intr(int irq, ide_hwgroup_t *hwgroup)
 {
 	byte stat;
-	ide_hwif_t *hwif = hwgroup->hwif;
+	struct ata_channel *hwif = hwgroup->hwif;
 
 	/*
 	 * handle the unexpected interrupt
@@ -1568,11 +1558,11 @@
 /*
  * entry point for all interrupts, caller does __cli() for us
  */
-void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
+void ide_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
 	unsigned long flags;
 	ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id;
-	ide_hwif_t *hwif;
+	struct ata_channel *hwif;
 	ide_drive_t *drive;
 	ide_handler_t *handler;
 	ide_startstop_t startstop;
@@ -1611,7 +1601,7 @@
 			 * Whack the status register, just in case we have a leftover pending IRQ.
 			 */
 			IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]);
-#endif /* CONFIG_BLK_DEV_IDEPCI */
+#endif
 		}
 		goto out_lock;
 	}
@@ -1650,8 +1640,8 @@
 	 * same irq as is currently being serviced here, and Linux
 	 * won't allow another of the same (on any CPU) until we return.
 	 */
-	set_recovery_timer(HWIF(drive));
-	drive->service_time = jiffies - drive->service_start;
+	set_recovery_timer(drive->channel);
+	drive->PADAM_service_time = jiffies - drive->PADAM_service_start;
 	if (startstop == ide_stopped) {
 		if (hwgroup->handler == NULL) {	/* paranoia */
 			clear_bit(IDE_BUSY, &hwgroup->flags);
@@ -1675,7 +1665,7 @@
 	int h;
 
 	for (h = 0; h < MAX_HWIFS; ++h) {
-		ide_hwif_t  *hwif = &ide_hwifs[h];
+		struct ata_channel *hwif = &ide_hwifs[h];
 		if (hwif->present && major == hwif->major) {
 			int unit = DEVICE_NR(i_rdev);
 			if (unit < MAX_DRIVES) {
@@ -1699,41 +1689,39 @@
 }
 
 /*
- * This function issues a special IDE device request
- * onto the request queue.
+ * 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_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_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_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.
+ * 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)
+int ide_do_drive_cmd(ide_drive_t *drive, struct request *rq, ide_action_t action)
 {
 	unsigned long flags;
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
-	unsigned int major = HWIF(drive)->major;
+	unsigned int major = drive->channel->major;
 	request_queue_t *q = &drive->queue;
 	struct list_head *queue_head = &q->queue_head;
 	DECLARE_COMPLETION(wait);
 
 #ifdef CONFIG_BLK_DEV_PDC4030
-	if (HWIF(drive)->chipset == ide_pdc4030 && rq->buffer != NULL)
+	if (drive->channel->chipset == ide_pdc4030 && rq->buffer != NULL)
 		return -ENOSYS;  /* special drive cmds not supported */
 #endif
 	rq->errors = 0;
@@ -1812,7 +1800,7 @@
  */
 void revalidate_drives(void)
 {
-	ide_hwif_t *hwif;
+	struct ata_channel *hwif;
 	ide_drive_t *drive;
 	int h;
 
@@ -1935,29 +1923,28 @@
  * Note that we only release the standard ports, and do not even try to handle
  * any extra ports allocated for weird IDE interface chipsets.
  */
-static void hwif_unregister(ide_hwif_t *hwif)
+static void hwif_unregister(struct ata_channel *hwif)
 {
 	if (hwif->straight8) {
 		ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 8);
-		goto jump_eight;
+	} else {
+		if (hwif->io_ports[IDE_DATA_OFFSET])
+			ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 1);
+		if (hwif->io_ports[IDE_ERROR_OFFSET])
+			ide_release_region(hwif->io_ports[IDE_ERROR_OFFSET], 1);
+		if (hwif->io_ports[IDE_NSECTOR_OFFSET])
+			ide_release_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1);
+		if (hwif->io_ports[IDE_SECTOR_OFFSET])
+			ide_release_region(hwif->io_ports[IDE_SECTOR_OFFSET], 1);
+		if (hwif->io_ports[IDE_LCYL_OFFSET])
+			ide_release_region(hwif->io_ports[IDE_LCYL_OFFSET], 1);
+		if (hwif->io_ports[IDE_HCYL_OFFSET])
+			ide_release_region(hwif->io_ports[IDE_HCYL_OFFSET], 1);
+		if (hwif->io_ports[IDE_SELECT_OFFSET])
+			ide_release_region(hwif->io_ports[IDE_SELECT_OFFSET], 1);
+		if (hwif->io_ports[IDE_STATUS_OFFSET])
+			ide_release_region(hwif->io_ports[IDE_STATUS_OFFSET], 1);
 	}
-	if (hwif->io_ports[IDE_DATA_OFFSET])
-		ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 1);
-	if (hwif->io_ports[IDE_ERROR_OFFSET])
-		ide_release_region(hwif->io_ports[IDE_ERROR_OFFSET], 1);
-	if (hwif->io_ports[IDE_NSECTOR_OFFSET])
-		ide_release_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1);
-	if (hwif->io_ports[IDE_SECTOR_OFFSET])
-		ide_release_region(hwif->io_ports[IDE_SECTOR_OFFSET], 1);
-	if (hwif->io_ports[IDE_LCYL_OFFSET])
-		ide_release_region(hwif->io_ports[IDE_LCYL_OFFSET], 1);
-	if (hwif->io_ports[IDE_HCYL_OFFSET])
-		ide_release_region(hwif->io_ports[IDE_HCYL_OFFSET], 1);
-	if (hwif->io_ports[IDE_SELECT_OFFSET])
-		ide_release_region(hwif->io_ports[IDE_SELECT_OFFSET], 1);
-	if (hwif->io_ports[IDE_STATUS_OFFSET])
-		ide_release_region(hwif->io_ports[IDE_STATUS_OFFSET], 1);
-jump_eight:
 	if (hwif->io_ports[IDE_CONTROL_OFFSET])
 		ide_release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
 #if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
@@ -1966,23 +1953,22 @@
 #endif
 }
 
-void ide_unregister(ide_hwif_t *hwif)
+void ide_unregister(struct ata_channel *channel)
 {
 	struct gendisk *gd;
 	ide_drive_t *drive, *d;
-	ide_hwif_t *g;
 	ide_hwgroup_t *hwgroup;
-	int irq_count = 0, unit, i;
+	int unit, i;
 	unsigned long flags;
 	unsigned int p, minor;
-	ide_hwif_t old_hwif;
+	struct ata_channel old_hwif;
 
 	spin_lock_irqsave(&ide_lock, flags);
-	if (!hwif->present)
+	if (!channel->present)
 		goto abort;
-	put_device(&hwif->device);
+	put_device(&channel->dev);
 	for (unit = 0; unit < MAX_DRIVES; ++unit) {
-		drive = &hwif->drives[unit];
+		drive = &channel->drives[unit];
 		if (!drive->present)
 			continue;
 		if (drive->busy || drive->usage)
@@ -1995,43 +1981,47 @@
 				ide_unregister_subdriver(drive);
 		}
 	}
-	hwif->present = 0;
+	channel->present = 0;
 
 	/*
 	 * All clear?  Then blow away the buffer cache
 	 */
 	spin_unlock_irqrestore(&ide_lock, flags);
 	for (unit = 0; unit < MAX_DRIVES; ++unit) {
-		drive = &hwif->drives[unit];
+		drive = &channel->drives[unit];
 		if (!drive->present)
 			continue;
 		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 = mk_kdev(hwif->major, minor+p);
+				kdev_t devp = mk_kdev(channel->major, minor+p);
 				invalidate_device(devp, 0);
 			}
 		}
 	}
 #ifdef CONFIG_PROC_FS
-	destroy_proc_ide_drives(hwif);
+	destroy_proc_ide_drives(channel);
 #endif
 	spin_lock_irqsave(&ide_lock, flags);
-	hwgroup = hwif->hwgroup;
+	hwgroup = channel->hwgroup;
 
 	/*
 	 * free the irq if we were the only hwif using it
 	 */
-	g = hwgroup->hwif;
-	do {
-		if (g->irq == hwif->irq)
-			++irq_count;
-		g = g->next;
-	} while (g != hwgroup->hwif);
-	if (irq_count == 1)
-		free_irq(hwif->irq, hwgroup);
+	{
+		struct ata_channel *g;
+		int irq_count = 0;
 
-	hwif_unregister(hwif);
+		g = hwgroup->hwif;
+		do {
+			if (g->irq == channel->irq)
+				++irq_count;
+			g = g->next;
+		} while (g != hwgroup->hwif);
+		if (irq_count == 1)
+			free_irq(channel->irq, hwgroup);
+	}
+	hwif_unregister(channel);
 
 	/*
 	 * Remove us from the hwgroup, and free
@@ -2039,7 +2029,7 @@
 	 */
 	d = hwgroup->drive;
 	for (i = 0; i < MAX_DRIVES; ++i) {
-		drive = &hwif->drives[i];
+		drive = &channel->drives[i];
 		if (drive->de) {
 			devfs_unregister (drive->de);
 			drive->de = NULL;
@@ -2060,27 +2050,27 @@
 	}
 	if (d->present)
 		hwgroup->drive = d;
-	while (hwgroup->hwif->next != hwif)
+	while (hwgroup->hwif->next != channel)
 		hwgroup->hwif = hwgroup->hwif->next;
-	hwgroup->hwif->next = hwif->next;
-	if (hwgroup->hwif == hwif)
+	hwgroup->hwif->next = channel->next;
+	if (hwgroup->hwif == channel)
 		kfree(hwgroup);
 	else
-		hwgroup->hwif = HWIF(hwgroup->drive);
+		hwgroup->hwif = hwgroup->drive->channel;
 
 #if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI)
-	ide_release_dma(hwif);
+	ide_release_dma(channel);
 #endif
 
 	/*
 	 * Remove us from the kernel's knowledge
 	 */
-	unregister_blkdev(hwif->major, hwif->name);
-	kfree(blksize_size[hwif->major]);
-	blk_dev[hwif->major].data = NULL;
-	blk_dev[hwif->major].queue = NULL;
-	blk_clear(hwif->major);
-	gd = hwif->gd;
+	unregister_blkdev(channel->major, channel->name);
+	kfree(blksize_size[channel->major]);
+	blk_dev[channel->major].data = NULL;
+	blk_dev[channel->major].queue = NULL;
+	blk_clear(channel->major);
+	gd = channel->gd;
 	if (gd) {
 		del_gendisk(gd);
 		kfree(gd->sizes);
@@ -2090,45 +2080,45 @@
 		if (gd->flags)
 			kfree (gd->flags);
 		kfree(gd);
-		hwif->gd = NULL;
+		channel->gd = NULL;
 	}
 
 	/*
-	 * Reinitialize the hwif handler, but preserve any special methods for
+	 * Reinitialize the channel handler, but preserve any special methods for
 	 * it.
 	 */
 
-	old_hwif		= *hwif;
-	init_hwif_data(hwif, hwif->index);
-	hwif->hwgroup		= old_hwif.hwgroup;
-	hwif->tuneproc		= old_hwif.tuneproc;
-	hwif->speedproc		= old_hwif.speedproc;
-	hwif->selectproc	= old_hwif.selectproc;
-	hwif->resetproc		= old_hwif.resetproc;
-	hwif->intrproc		= old_hwif.intrproc;
-	hwif->maskproc		= old_hwif.maskproc;
-	hwif->quirkproc		= old_hwif.quirkproc;
-	hwif->rwproc		= old_hwif.rwproc;
-	hwif->ideproc		= old_hwif.ideproc;
-	hwif->dmaproc		= old_hwif.dmaproc;
-	hwif->busproc		= old_hwif.busproc;
-	hwif->bus_state		= old_hwif.bus_state;
-	hwif->dma_base		= old_hwif.dma_base;
-	hwif->dma_extra		= old_hwif.dma_extra;
-	hwif->config_data	= old_hwif.config_data;
-	hwif->select_data	= old_hwif.select_data;
-	hwif->proc		= old_hwif.proc;
+	old_hwif		= *channel;
+	init_hwif_data(channel, channel->index);
+	channel->hwgroup = old_hwif.hwgroup;
+	channel->tuneproc = old_hwif.tuneproc;
+	channel->speedproc = old_hwif.speedproc;
+	channel->selectproc = old_hwif.selectproc;
+	channel->resetproc = old_hwif.resetproc;
+	channel->intrproc = old_hwif.intrproc;
+	channel->maskproc = old_hwif.maskproc;
+	channel->quirkproc = old_hwif.quirkproc;
+	channel->rwproc	= old_hwif.rwproc;
+	channel->ideproc = old_hwif.ideproc;
+	channel->dmaproc = old_hwif.dmaproc;
+	channel->busproc = old_hwif.busproc;
+	channel->bus_state = old_hwif.bus_state;
+	channel->dma_base = old_hwif.dma_base;
+	channel->dma_extra = old_hwif.dma_extra;
+	channel->config_data = old_hwif.config_data;
+	channel->select_data = old_hwif.select_data;
+	channel->proc = old_hwif.proc;
 #ifndef CONFIG_BLK_DEV_IDECS
-	hwif->irq		= old_hwif.irq;
+	channel->irq = old_hwif.irq;
 #endif
-	hwif->major		= old_hwif.major;
-	hwif->chipset		= old_hwif.chipset;
-	hwif->autodma		= old_hwif.autodma;
-	hwif->udma_four		= old_hwif.udma_four;
+	channel->major = old_hwif.major;
+	channel->chipset = old_hwif.chipset;
+	channel->autodma = old_hwif.autodma;
+	channel->udma_four = old_hwif.udma_four;
 #ifdef CONFIG_BLK_DEV_IDEPCI
-	hwif->pci_dev		= old_hwif.pci_dev;
+	channel->pci_dev = old_hwif.pci_dev;
 #endif
-	hwif->straight8		= old_hwif.straight8;
+	channel->straight8 = old_hwif.straight8;
 abort:
 	spin_unlock_irqrestore(&ide_lock, flags);
 }
@@ -2173,10 +2163,11 @@
  * 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 ide_register_hw(hw_regs_t *hw, struct ata_channel **hwifp)
 {
-	int h, retry = 1;
-	ide_hwif_t *hwif;
+	int h;
+	int retry = 1;
+	struct ata_channel *hwif;
 
 	do {
 		for (h = 0; h < MAX_HWIFS; ++h) {
@@ -2193,7 +2184,9 @@
 		for (h = 0; h < MAX_HWIFS; ++h)
 			ide_unregister(&ide_hwifs[h]);
 	} while (retry--);
+
 	return -1;
+
 found:
 	ide_unregister(hwif);
 	if (hwif->present)
@@ -2375,8 +2368,8 @@
 {
 	drive->io_32bit = arg;
 #ifdef CONFIG_BLK_DEV_DTC2278
-	if (HWIF(drive)->chipset == ide_dtc2278)
-		HWIF(drive)->drives[!drive->select.b.unit].io_32bit = arg;
+	if (drive->channel->chipset == ide_dtc2278)
+		drive->channel->drives[!drive->select.b.unit].io_32bit = arg;
 #endif /* CONFIG_BLK_DEV_DTC2278 */
 	return 0;
 }
@@ -2385,9 +2378,9 @@
 {
 	if (!drive->driver)
 		return -EPERM;
-	if (!drive->id || !(drive->id->capability & 1) || !HWIF(drive)->dmaproc)
+	if (!drive->id || !(drive->id->capability & 1) || !drive->channel->dmaproc)
 		return -EPERM;
-	if (HWIF(drive)->dmaproc(arg ? ide_dma_on : ide_dma_off, drive))
+	if (drive->channel->dmaproc(arg ? ide_dma_on : ide_dma_off, drive))
 		return -EIO;
 	return 0;
 }
@@ -2396,14 +2389,14 @@
 {
 	struct request rq;
 
-	if (!HWIF(drive)->tuneproc)
+	if (!drive->channel->tuneproc)
 		return -ENOSYS;
 	if (drive->special.b.set_tune)
 		return -EBUSY;
 	ide_init_drive_cmd(&rq);
 	drive->tune_req = (byte) arg;
 	drive->special.b.set_tune = 1;
-	(void) ide_do_drive_cmd (drive, &rq, ide_wait);
+	ide_do_drive_cmd(drive, &rq, ide_wait);
 	return 0;
 }
 
@@ -2414,7 +2407,6 @@
  */
 	ide_add_setting(drive,	"io_32bit",		drive->no_io_32bit ? SETTING_READ : SETTING_RW,	HDIO_GET_32BIT,		HDIO_SET_32BIT,		TYPE_BYTE,	0,	1 + (SUPPORT_VLB_SYNC << 1),	1,		1,		&drive->io_32bit,		set_io_32bit);
 	ide_add_setting(drive,	"keepsettings",		SETTING_RW,					HDIO_GET_KEEPSETTINGS,	HDIO_SET_KEEPSETTINGS,	TYPE_BYTE,	0,	1,				1,		1,		&drive->keep_settings,		NULL);
-	ide_add_setting(drive,	"nice1",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	1,				1,		1,		&drive->nice1,			NULL);
 	ide_add_setting(drive,	"pio_mode",		SETTING_WRITE,					-1,			HDIO_SET_PIO_MODE,	TYPE_BYTE,	0,	255,				1,		1,		NULL,				set_pio_mode);
 	ide_add_setting(drive,	"slow",			SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	1,				1,		1,		&drive->slow,			NULL);
 	ide_add_setting(drive,	"unmaskirq",		drive->no_unmask ? SETTING_READ : SETTING_RW,	HDIO_GET_UNMASKINTR,	HDIO_SET_UNMASKINTR,	TYPE_BYTE,	0,	1,				1,		1,		&drive->unmask,			NULL);
@@ -2540,10 +2532,7 @@
 
 		case HDIO_GET_NICE:
 			return put_user(drive->dsc_overlap	<<	IDE_NICE_DSC_OVERLAP	|
-					drive->atapi_overlap	<<	IDE_NICE_ATAPI_OVERLAP	|
-					drive->nice0		<< 	IDE_NICE_0		|
-					drive->nice1		<<	IDE_NICE_1		|
-					drive->nice2		<<	IDE_NICE_2,
+					drive->atapi_overlap	<<	IDE_NICE_ATAPI_OVERLAP,
 					(long *) arg);
 
 		case HDIO_DRIVE_CMD:
@@ -2558,7 +2547,7 @@
 
 		case HDIO_SET_NICE:
 			if (!capable(CAP_SYS_ADMIN)) return -EACCES;
-			if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1))))
+			if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP))))
 				return -EPERM;
 			drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1;
 			/* Only CD-ROM's and tapes support DSC overlap. */
@@ -2566,7 +2555,6 @@
 				drive->dsc_overlap = 0;
 				return -EPERM;
 			}
-			drive->nice1 = (arg >> IDE_NICE_1) & 1;
 			return 0;
 		case BLKGETSIZE:
 		case BLKGETSIZE64:
@@ -2591,15 +2579,15 @@
 		case HDIO_GET_BUSSTATE:
 			if (!capable(CAP_SYS_ADMIN))
 				return -EACCES;
-			if (put_user(HWIF(drive)->bus_state, (long *)arg))
+			if (put_user(drive->channel->bus_state, (long *)arg))
 				return -EFAULT;
 			return 0;
 
 		case HDIO_SET_BUSSTATE:
 			if (!capable(CAP_SYS_ADMIN))
 				return -EACCES;
-			if (HWIF(drive)->busproc)
-				HWIF(drive)->busproc(drive, (int)arg);
+			if (drive->channel->busproc)
+				drive->channel->busproc(drive, (int)arg);
 			return 0;
 
 		default:
@@ -2802,7 +2790,7 @@
 int __init ide_setup (char *s)
 {
 	int i, vals[3];
-	ide_hwif_t *hwif;
+	struct ata_channel *hwif;
 	ide_drive_t *drive;
 	unsigned int hw, unit;
 	const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1);
@@ -3116,7 +3104,7 @@
 	unsigned int unit, index, i;
 
 	for (index = 0, i = 0; index < MAX_HWIFS; ++index) {
-		ide_hwif_t *hwif = &ide_hwifs[index];
+		struct ata_channel *hwif = &ide_hwifs[index];
 		if (!hwif->present)
 			continue;
 		for (unit = 0; unit < MAX_DRIVES; ++unit) {
@@ -3146,7 +3134,7 @@
 	}
 
 	/* FIXME: This will be pushed to the drivers! Thus allowing us to
-	 * save one parameter here eparate this out.
+	 * save one parameter here separate this out.
 	 */
 
 	drive->driver = driver;
@@ -3154,7 +3142,7 @@
 	restore_flags(flags);		/* all CPUs */
 	/* FIXME: Check what this magic number is supposed to be about? */
 	if (drive->autotune != 2) {
-		if (HWIF(drive)->dmaproc != NULL) {
+		if (drive->channel->dmaproc != NULL) {
 
 			/*
 			 * Force DMAing for the beginning of the check.  Some
@@ -3164,13 +3152,12 @@
 			 *   PARANOIA!!!
 			 */
 
-			HWIF(drive)->dmaproc(ide_dma_off_quietly, drive);
-			HWIF(drive)->dmaproc(ide_dma_check, drive);
+			drive->channel->dmaproc(ide_dma_off_quietly, drive);
+			drive->channel->dmaproc(ide_dma_check, drive);
 		}
 		/* Only CD-ROMs and tape drives support DSC overlap. */
 		drive->dsc_overlap = (drive->next != drive
 				&& (drive->type == ATA_ROM || drive->type == ATA_TAPE));
-		drive->nice1 = 1;
 	}
 	drive->revalidate = 1;
 	drive->suspend_reset = 0;
@@ -3193,10 +3180,19 @@
 
 	save_flags(flags);		/* all CPUs */
 	cli();				/* all CPUs */
-	if (drive->usage || drive->busy || !ata_ops(drive) || ata_ops(drive)->busy) {
+
+#if 0
+	if (__MOD_IN_USE(ata_ops(drive)->owner)) {
+		restore_flags(flags);
+		return 1;
+	}
+#endif
+
+	if (drive->usage || drive->busy || !ata_ops(drive)) {
 		restore_flags(flags);	/* all CPUs */
 		return 1;
 	}
+
 #if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP) && defined(MODULE)
 	pnpide_init(0);
 #endif
@@ -3207,7 +3203,10 @@
 #endif
 	auto_remove_settings(drive);
 	drive->driver = NULL;
+	drive->present = 0;
+
 	restore_flags(flags);		/* all CPUs */
+
 	return 0;
 }
 
@@ -3297,7 +3296,7 @@
 
 static int ide_notify_reboot (struct notifier_block *this, unsigned long event, void *x)
 {
-	ide_hwif_t *hwif;
+	struct ata_channel *hwif;
 	ide_drive_t *drive;
 	int i, unit;
 
@@ -3316,6 +3315,7 @@
 		hwif = &ide_hwifs[i];
 		if (!hwif->present)
 			continue;
+
 		for (unit = 0; unit < MAX_DRIVES; ++unit) {
 			drive = &hwif->drives[unit];
 			if (!drive->present)
@@ -3479,12 +3479,13 @@
 	initializing = 0;
 
 	for (h = 0; h < MAX_HWIFS; ++h) {
-		ide_hwif_t  *hwif = &ide_hwifs[h];
-		if (hwif->present)
-			ide_geninit(hwif);
+		struct ata_channel *channel = &ide_hwifs[h];
+		if (channel->present)
+			ide_geninit(channel);
 	}
 
 	register_reboot_notifier(&ide_notifier);
+
 	return 0;
 }
 
diff --git a/drivers/ide/it8172.c b/drivers/ide/it8172.c
index 12b6fae..6e6a864 100644
--- a/drivers/ide/it8172.c
+++ b/drivers/ide/it8172.c
@@ -53,7 +53,7 @@
 static int it8172_config_drive_for_dma (ide_drive_t *drive);
 static int it8172_dmaproc(ide_dma_action_t func, ide_drive_t *drive);
 #endif
-void __init ide_init_it8172 (ide_hwif_t *hwif);
+void __init ide_init_it8172(struct ata_channel *channel);
 
 
 static void it8172_tune_drive (ide_drive_t *drive, byte pio)
@@ -61,7 +61,7 @@
     unsigned long flags;
     u16 master_data;
     u32 slave_data;
-    int is_slave	= (&HWIF(drive)->drives[1] == drive);
+    int is_slave	= (&drive->channel->drives[1] == drive);
     int master_port	= 0x40;
     int slave_port      = 0x44;
 
@@ -70,8 +70,8 @@
     else
        pio = min_t(byte, pio, 4);
 
-    pci_read_config_word(HWIF(drive)->pci_dev, master_port, &master_data);
-    pci_read_config_dword(HWIF(drive)->pci_dev, slave_port, &slave_data);
+    pci_read_config_word(drive->channel->pci_dev, master_port, &master_data);
+    pci_read_config_dword(drive->channel->pci_dev, slave_port, &slave_data);
 
     /*
      * FIX! The DIOR/DIOW pulse width and recovery times in port 0x44
@@ -94,7 +94,7 @@
 
     save_flags(flags);
     cli();
-    pci_write_config_word(HWIF(drive)->pci_dev, master_port, master_data);
+    pci_write_config_word(drive->channel->pci_dev, master_port, master_data);
     restore_flags(flags);
 }
 
@@ -133,7 +133,7 @@
 
 static int it8172_tune_chipset (ide_drive_t *drive, byte speed)
 {
-    ide_hwif_t *hwif	= HWIF(drive);
+    struct ata_channel *hwif = drive->channel;
     struct pci_dev *dev	= hwif->pci_dev;
     int a_speed		= 3 << (drive->dn * 4);
     int u_flag		= 1 << drive->dn;
@@ -231,7 +231,7 @@
 }
 
 
-void __init ide_init_it8172 (ide_hwif_t *hwif)
+void __init ide_init_it8172(struct ata_channel *hwif)
 {
     struct pci_dev* dev = hwif->pci_dev;
     unsigned long cmdBase, ctrlBase;
diff --git a/drivers/ide/macide.c b/drivers/ide/macide.c
index d28eac4..6b74ade 100644
--- a/drivers/ide/macide.c
+++ b/drivers/ide/macide.c
@@ -69,7 +69,7 @@
     IDE_HCYL, IDE_SELECT, IDE_STATUS,  IDE_CONTROL
 };
 
-int macide_ack_intr(ide_hwif_t* hwif)
+int macide_ack_intr(struct ata_channel *hwif)
 {
 	if (*ide_ifr & 0x20) {
 		*ide_ifr &= ~0x20;
diff --git a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c
index c29dd4a..787cc4b 100644
--- a/drivers/ide/ns87415.c
+++ b/drivers/ide/ns87415.c
@@ -28,12 +28,12 @@
 
 /*
  * This routine either enables/disables (according to drive->present)
- * the IRQ associated with the port (HWIF(drive)),
+ * the IRQ associated with the port (drive->channel),
  * and selects either PIO or DMA handshaking for the next I/O operation.
  */
 static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	unsigned int bit, other, new, *old = (unsigned int *) hwif->select_data;
 	struct pci_dev *dev = hwif->pci_dev;
 	unsigned long flags;
@@ -43,12 +43,12 @@
 	new = *old;
 
 	/* Adjust IRQ enable bit */
-	bit = 1 << (8 + hwif->channel);
+	bit = 1 << (8 + hwif->unit);
 	new = drive->present ? (new & ~bit) : (new | bit);
 
 	/* Select PIO or DMA, DMA may only be selected for one drive/channel. */
-	bit   = 1 << (20 + drive->select.b.unit       + (hwif->channel << 1));
-	other = 1 << (20 + (1 - drive->select.b.unit) + (hwif->channel << 1));
+	bit   = 1 << (20 + drive->select.b.unit       + (hwif->unit << 1));
+	other = 1 << (20 + (1 - drive->select.b.unit) + (hwif->unit << 1));
 	new = use_dma ? ((new & ~other) | bit) : (new & ~bit);
 
 	if (new != *old) {
@@ -84,7 +84,7 @@
 #ifdef CONFIG_BLK_DEV_IDEDMA
 static int ns87415_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
 {
-	ide_hwif_t	*hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	byte		dma_stat;
 
 	switch (func) {
@@ -112,7 +112,7 @@
 }
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
-void __init ide_init_ns87415 (ide_hwif_t *hwif)
+void __init ide_init_ns87415(struct ata_channel *hwif)
 {
 	struct pci_dev *dev = hwif->pci_dev;
 	unsigned int ctrl, using_inta;
@@ -138,9 +138,9 @@
 	(void) pci_read_config_dword(dev, 0x40, &ctrl);
 	(void) pci_read_config_byte(dev, 0x09, &progif);
 	/* is irq in "native" mode? */
-	using_inta = progif & (1 << (hwif->channel << 1));
+	using_inta = progif & (1 << (hwif->unit << 1));
 	if (!using_inta)
-		using_inta = ctrl & (1 << (4 + hwif->channel));
+		using_inta = ctrl & (1 << (4 + hwif->unit));
 	if (hwif->mate) {
 		hwif->select_data = hwif->mate->select_data;
 	} else {
@@ -180,7 +180,7 @@
 		outb(0x60, hwif->dma_base + 2);
 
 	if (!using_inta)
-		hwif->irq = hwif->channel ? 15 : 14;	/* legacy mode */
+		hwif->irq = hwif->unit ? 15 : 14;	/* legacy mode */
 	else if (!hwif->irq && hwif->mate && hwif->mate->irq)
 		hwif->irq = hwif->mate->irq;	/* share IRQ with mate */
 
diff --git a/drivers/ide/opti621.c b/drivers/ide/opti621.c
index 4b5c901..7003b8d 100644
--- a/drivers/ide/opti621.c
+++ b/drivers/ide/opti621.c
@@ -142,7 +142,7 @@
  */
 {
 	int d;
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 
 	if (pio == PIO_DONT_KNOW)
 		drive->drive_data = min(ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0, OPTI621_MAX_PIO);
@@ -252,7 +252,7 @@
 	pio_clocks_t first, second;
 	int ax, drdy;
 	byte cycle1, cycle2, misc;
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 
 	/* sets drive->drive_data for both drives */
 	compute_pios(drive, pio);
@@ -310,7 +310,7 @@
 /*
  * ide_init_opti621() is called once for each hwif found at boot.
  */
-void __init ide_init_opti621 (ide_hwif_t *hwif)
+void __init ide_init_opti621(struct ata_channel *hwif)
 {
 	hwif->drives[0].drive_data = PIO_DONT_KNOW;
 	hwif->drives[1].drive_data = PIO_DONT_KNOW;
diff --git a/drivers/ide/pdc202xx.c b/drivers/ide/pdc202xx.c
index 9d07276..1ff23c4 100644
--- a/drivers/ide/pdc202xx.c
+++ b/drivers/ide/pdc202xx.c
@@ -217,6 +217,9 @@
 		case PCI_DEVICE_ID_PROMISE_20275:
 			p += sprintf(p, "\n                                PDC20275 Chipset.\n");
 			break;
+		case PCI_DEVICE_ID_PROMISE_20276:
+			p += sprintf(p, "\n                                PDC20276 Chipset.\n");
+			break;
 		case PCI_DEVICE_ID_PROMISE_20269:
 			p += sprintf(p, "\n                                PDC20269 TX2 Chipset.\n");
 			break;
@@ -236,6 +239,7 @@
 	char *p = buffer;
 	switch(bmide_dev->device) {
 		case PCI_DEVICE_ID_PROMISE_20275:
+		case PCI_DEVICE_ID_PROMISE_20276:
 		case PCI_DEVICE_ID_PROMISE_20269:
 		case PCI_DEVICE_ID_PROMISE_20268:
 		case PCI_DEVICE_ID_PROMISE_20268R:
@@ -395,8 +399,8 @@
 
 static int pdc202xx_tune_chipset (ide_drive_t *drive, byte speed)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct ata_channel *hwif = drive->channel;
+	struct pci_dev *dev = hwif->pci_dev;
 
 	unsigned int		drive_conf;
 	int			err;
@@ -519,14 +523,14 @@
 
 static int pdc202xx_new_tune_chipset (ide_drive_t *drive, byte speed)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	unsigned long indexreg	= (hwif->dma_base + 1);
 	unsigned long datareg	= (hwif->dma_base + 3);
 #else
 	struct pci_dev *dev	= hwif->pci_dev;
 	unsigned long high_16	= pci_resource_start(dev, 4);
-	unsigned long indexreg	= high_16 + (hwif->channel ? 0x09 : 0x01);
+	unsigned long indexreg	= high_16 + (hwif->unit ? 0x09 : 0x01);
 	unsigned long datareg	= (indexreg + 2);
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 	byte thold		= 0x10;
@@ -660,6 +664,7 @@
 			OUT_BYTE(0xac, datareg);
 			break;
 		default:
+			;
 	}
 
 	if (!drive->init_speed)
@@ -698,7 +703,7 @@
 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 ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 	unsigned long high_16   = pci_resource_start(dev, 4);
 	unsigned long dma_base  = hwif->dma_base;
@@ -720,8 +725,8 @@
 	byte udma_66		= ((eighty_ninty_three(drive)) && udma_33) ? 1 : 0;
 	byte udma_100		= 0;
 	byte udma_133		= 0;
-	byte mask		= hwif->channel ? 0x08 : 0x02;
-	unsigned short c_mask	= hwif->channel ? (1<<11) : (1<<10);
+	byte mask		= hwif->unit ? 0x08 : 0x02;
+	unsigned short c_mask	= hwif->unit ? (1<<11) : (1<<10);
 
 	byte ultra_66		= ((id->dma_ultra & 0x0010) ||
 				   (id->dma_ultra & 0x0008)) ? 1 : 0;
@@ -732,6 +737,7 @@
 
 	switch(dev->device) {
 		case PCI_DEVICE_ID_PROMISE_20275:
+		case PCI_DEVICE_ID_PROMISE_20276:
 		case PCI_DEVICE_ID_PROMISE_20269:
 			udma_133 = (udma_66) ? 1 : 0;
 			udma_100 = (udma_66) ? 1 : 0;
@@ -786,14 +792,14 @@
 
 	if (((ultra_66) || (ultra_100) || (ultra_133)) && (cable)) {
 #ifdef DEBUG
-		printk("ULTRA66: %s channel of Ultra 66 requires an 80-pin cable for Ultra66 operation.\n", hwif->channel ? "Secondary" : "Primary");
+		printk("ULTRA66: %s channel of Ultra 66 requires an 80-pin cable for Ultra66 operation.\n", hwif->unit ? "Secondary" : "Primary");
 		printk("         Switching to Ultra33 mode.\n");
 #endif /* DEBUG */
 		/* Primary   : zero out second bit */
 		/* Secondary : zero out fourth bit */
 		if (!jumpbit)
 			OUT_BYTE(CLKSPD & ~mask, (high_16 + 0x11));
-		printk("Warning: %s channel requires an 80-pin cable for operation.\n", hwif->channel ? "Secondary":"Primary");
+		printk("Warning: %s channel requires an 80-pin cable for operation.\n", hwif->unit ? "Secondary":"Primary");
 		printk("%s reduced to Ultra33 mode.\n", drive->name);
 		udma_66 = 0; udma_100 = 0; udma_133 = 0;
 	} else {
@@ -918,7 +924,7 @@
 static int config_drive_xfer_rate (ide_drive_t *drive)
 {
 	struct hd_driveid *id = drive->id;
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	ide_dma_action_t dma_func = ide_dma_off_quietly;
 
 	if (id && (id->capability & 1) && hwif->autodma) {
@@ -963,7 +969,7 @@
 		(void) config_chipset_for_pio(drive, 5);
 	}
 
-	return HWIF(drive)->dmaproc(dma_func, drive);
+	return drive->channel->dmaproc(dma_func, drive);
 }
 
 int pdc202xx_quirkproc (ide_drive_t *drive)
@@ -981,14 +987,15 @@
 	byte newchip		= 0;
 	byte clock		= 0;
 	byte hardware48hack	= 0;
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 	unsigned long high_16	= pci_resource_start(dev, 4);
-	unsigned long atapi_reg	= high_16 + (hwif->channel ? 0x24 : 0x00);
+	unsigned long atapi_reg	= high_16 + (hwif->unit ? 0x24 : 0x00);
 	unsigned long dma_base	= hwif->dma_base;
 
 	switch (dev->device) {
 		case PCI_DEVICE_ID_PROMISE_20275:
+		case PCI_DEVICE_ID_PROMISE_20276:
 		case PCI_DEVICE_ID_PROMISE_20269:
 		case PCI_DEVICE_ID_PROMISE_20268R:
 		case PCI_DEVICE_ID_PROMISE_20268:
@@ -1016,7 +1023,7 @@
 				struct request *rq = HWGROUP(drive)->rq;
 				unsigned long word_count = 0;
 
-				outb(clock|(hwif->channel ? 0x08 : 0x02), high_16 + 0x11);
+				outb(clock|(hwif->unit ? 0x08 : 0x02), high_16 + 0x11);
 				word_count = (rq->nr_sectors << 8);
 				word_count = (rq_data_dir(rq) == READ) ? word_count | 0x05000000 : word_count | 0x06000000;
 				outl(word_count, atapi_reg);
@@ -1026,7 +1033,7 @@
 			if ((drive->addressing) && (hardware48hack)) {
 				outl(0, atapi_reg);	/* zero out extra */
 				clock = IN_BYTE(high_16 + 0x11);
-				OUT_BYTE(clock & ~(hwif->channel ? 0x08:0x02), high_16 + 0x11);
+				OUT_BYTE(clock & ~(hwif->unit ? 0x08:0x02), high_16 + 0x11);
 			}
 			break;
 		case ide_dma_test_irq:	/* returns 1 if dma irq issued, 0 otherwise */
@@ -1035,7 +1042,7 @@
 				return (dma_stat & 4) == 4;
 
 			sc1d = IN_BYTE(high_16 + 0x001d);
-			if (HWIF(drive)->channel) {
+			if (drive->channel->unit) {
 				if ((sc1d & 0x50) == 0x50) goto somebody_else;
 				else if ((sc1d & 0x40) == 0x40)
 					return (dma_stat & 4) == 4;
@@ -1048,8 +1055,8 @@
 			return (dma_stat & 4) == 4;	/* return 1 if INTR asserted */
 		case ide_dma_lostirq:
 		case ide_dma_timeout:
-			if (HWIF(drive)->resetproc != NULL)
-				HWIF(drive)->resetproc(drive);
+			if (drive->channel->resetproc != NULL)
+				drive->channel->resetproc(drive);
 		default:
 			break;
 	}
@@ -1064,12 +1071,12 @@
 	OUT_BYTE(0x00,IDE_CONTROL_REG);
 	mdelay(1000);
 	printk("PDC202XX: %s channel reset.\n",
-		HWIF(drive)->channel ? "Secondary" : "Primary");
+		drive->channel->unit ? "Secondary" : "Primary");
 }
 
 void pdc202xx_reset (ide_drive_t *drive)
 {
-	unsigned long high_16	= pci_resource_start(HWIF(drive)->pci_dev, 4);
+	unsigned long high_16	= pci_resource_start(drive->channel->pci_dev, 4);
 	byte udma_speed_flag	= IN_BYTE(high_16 + 0x001f);
 
 	OUT_BYTE(udma_speed_flag | 0x10, high_16 + 0x001f);
@@ -1077,7 +1084,7 @@
 	OUT_BYTE(udma_speed_flag & ~0x10, high_16 + 0x001f);
 	mdelay(2000);		/* 2 seconds ?! */
 	printk("PDC202XX: %s channel reset.\n",
-		HWIF(drive)->channel ? "Secondary" : "Primary");
+		drive->channel->unit ? "Secondary" : "Primary");
 }
 
 /*
@@ -1088,7 +1095,7 @@
 static int pdc202xx_tristate (ide_drive_t * drive, int state)
 {
 #if 0
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	unsigned long high_16	= pci_resource_start(hwif->pci_dev, 4);
 	byte sc1f		= inb(high_16 + 0x001f);
 
@@ -1121,6 +1128,7 @@
 
 	switch (dev->device) {
 		case PCI_DEVICE_ID_PROMISE_20275:
+		case PCI_DEVICE_ID_PROMISE_20276:
 		case PCI_DEVICE_ID_PROMISE_20269:
 		case PCI_DEVICE_ID_PROMISE_20268R:
 		case PCI_DEVICE_ID_PROMISE_20268:
@@ -1208,13 +1216,14 @@
 	return dev->irq;
 }
 
-unsigned int __init ata66_pdc202xx (ide_hwif_t *hwif)
+unsigned int __init ata66_pdc202xx(struct ata_channel *hwif)
 {
-	unsigned short mask = (hwif->channel) ? (1<<11) : (1<<10);
+	unsigned short mask = (hwif->unit) ? (1<<11) : (1<<10);
 	unsigned short CIS;
 
         switch(hwif->pci_dev->device) {
 		case PCI_DEVICE_ID_PROMISE_20275:
+		case PCI_DEVICE_ID_PROMISE_20276:
 		case PCI_DEVICE_ID_PROMISE_20269:
 		case PCI_DEVICE_ID_PROMISE_20268:
 		case PCI_DEVICE_ID_PROMISE_20268R:
@@ -1226,13 +1235,14 @@
 	}
 }
 
-void __init ide_init_pdc202xx (ide_hwif_t *hwif)
+void __init ide_init_pdc202xx(struct ata_channel *hwif)
 {
 	hwif->tuneproc  = &pdc202xx_tune_drive;
 	hwif->quirkproc = &pdc202xx_quirkproc;
 
         switch(hwif->pci_dev->device) {
 		case PCI_DEVICE_ID_PROMISE_20275:
+		case PCI_DEVICE_ID_PROMISE_20276:
 		case PCI_DEVICE_ID_PROMISE_20269:
 		case PCI_DEVICE_ID_PROMISE_20268:
 		case PCI_DEVICE_ID_PROMISE_20268R:
diff --git a/drivers/ide/pdc4030.c b/drivers/ide/pdc4030.c
index 04e6ad2..70408f3 100644
--- a/drivers/ide/pdc4030.c
+++ b/drivers/ide/pdc4030.c
@@ -99,7 +99,7 @@
 {
 	unsigned int number;
 
-	number = (HWIF(drive)->channel << 1) + drive->select.b.unit;
+	number = (drive->channel->unit << 1) + drive->select.b.unit;
 	OUT_BYTE(number,IDE_FEATURE_REG);
 }
 
@@ -155,10 +155,10 @@
  * setup_pdc4030()
  * Completes the setup of a Promise DC4030 controller card, once found.
  */
-int __init setup_pdc4030 (ide_hwif_t *hwif)
+int __init setup_pdc4030(struct ata_channel *hwif)
 {
         ide_drive_t *drive;
-	ide_hwif_t *hwif2;
+	struct ata_channel *hwif2;
 	struct dc_ident ident;
 	int i;
 	ide_startstop_t startstop;
@@ -226,13 +226,13 @@
 	hwif->chipset	= hwif2->chipset = ide_pdc4030;
 	hwif->mate	= hwif2;
 	hwif2->mate	= hwif;
-	hwif2->channel	= 1;
+	hwif2->unit	= 1;
 	hwif->selectproc = hwif2->selectproc = &promise_selectproc;
 	hwif->serialized = hwif2->serialized = 1;
 
 /* Shift the remaining interfaces down by one */
 	for (i=MAX_HWIFS-1 ; i > hwif->index+1 ; i--) {
-		ide_hwif_t *h = &ide_hwifs[i];
+		struct ata_channel *h = &ide_hwifs[i];
 
 #ifdef DEBUG
 		printk(KERN_DEBUG "Shifting i/f %d values to i/f %d\n",i-1,i);
@@ -263,7 +263,7 @@
  * Tests for the presence of a DC4030 Promise card on this interface
  * Returns: 1 if found, 0 if not found
  */
-int __init detect_pdc4030(ide_hwif_t *hwif)
+int __init detect_pdc4030(struct ata_channel *hwif)
 {
 	ide_drive_t *drive = &hwif->drives[0];
 
@@ -288,7 +288,7 @@
 void __init ide_probe_for_pdc4030(void)
 {
 	unsigned int	index;
-	ide_hwif_t	*hwif;
+	struct ata_channel *hwif;
 
 	if (enable_promise_support == 0)
 		return;
@@ -394,6 +394,7 @@
 
 	if (GET_STAT() & BUSY_STAT) {
 		if (time_before(jiffies, hwgroup->poll_timeout)) {
+			BUG_ON(HWGROUP(drive)->handler);
 			ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL);
 			return ide_started; /* continue polling... */
 		}
@@ -476,6 +477,7 @@
 
 	if (IN_BYTE(IDE_NSECTOR_REG) != 0) {
 		if (time_before(jiffies, hwgroup->poll_timeout)) {
+			BUG_ON(HWGROUP(drive)->handler);
 			ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL);
 			return ide_started; /* continue polling... */
 		}
@@ -489,6 +491,7 @@
 	 */
 	promise_multwrite(drive, 4);
 	hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
+	BUG_ON(HWGROUP(drive)->handler);
 	ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL);
 #ifdef DEBUG_WRITE
 	printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n",
@@ -523,6 +526,7 @@
 		if (promise_multwrite(drive, rq->nr_sectors - 4))
 			return ide_stopped;
 		hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
+		BUG_ON(HWGROUP(drive)->handler);
 		ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL);
 		return ide_started;
 	} else {
@@ -533,6 +537,7 @@
 		if (promise_multwrite(drive, rq->nr_sectors))
 			return ide_stopped;
 		hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
+		BUG_ON(HWGROUP(drive)->handler);
 		ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL);
 #ifdef DEBUG_WRITE
 		printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, "
@@ -549,14 +554,21 @@
  */
 ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task)
 {
-	struct request *rq	= HWGROUP(drive)->rq;
-	task_struct_t *taskfile	= (task_struct_t *) task->tfRegister;
+	struct request *rq = HWGROUP(drive)->rq;
+	struct hd_drive_task_hdr *taskfile = &task->taskfile;
 	unsigned long timeout;
 	byte stat;
 
+	/* Check that it's a regular command. If not, bomb out early. */
+	if (!(rq->flags & REQ_CMD)) {
+		blk_dump_rq_flags(rq, "pdc4030 bad flags");
+		ide_end_request(drive, 0);
+		return ide_stopped;
+	}
+
 	if (IDE_CONTROL_REG)
 		OUT_BYTE(drive->ctl, IDE_CONTROL_REG);  /* clear nIEN */
-	SELECT_MASK(HWIF(drive), drive, 0);
+	SELECT_MASK(drive->channel, drive, 0);
 
 	OUT_BYTE(taskfile->feature, IDE_FEATURE_REG);
 	OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG);
@@ -568,20 +580,12 @@
 	OUT_BYTE(taskfile->device_head, IDE_SELECT_REG);
 	OUT_BYTE(taskfile->command, IDE_COMMAND_REG);
 
-/* Check that it's a regular command. If not, bomb out early. */
-	if (!(rq->flags & REQ_CMD)) {
-		blk_dump_rq_flags(rq, "pdc4030 bad flags");
-		ide_end_request(drive, 0);
-		return ide_stopped;
-	}
-
 	switch (rq_data_dir(rq)) {
 	case READ:
-		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 
+ * 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.
@@ -600,6 +604,7 @@
 				printk(KERN_DEBUG "%s: read: waiting for "
 				                  "interrupt\n", drive->name);
 #endif
+				BUG_ON(HWGROUP(drive)->handler);
 				ide_set_handler(drive, &promise_read_intr, WAIT_CMD, NULL);
 				return ide_started;
 			}
@@ -612,7 +617,6 @@
 
 	case WRITE: {
 		ide_startstop_t startstop;
-		OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG);
 /*
  * Strategy on write is:
  *	look for the DRQ that should have been immediately asserted
@@ -624,7 +628,7 @@
 			printk(KERN_ERR "%s: no DRQ after issuing "
 			       "PROMISE_WRITE\n", drive->name);
 			return startstop;
-	    	}
+		}
 		if (!drive->unmask)
 			__cli();	/* local CPU only */
 		HWGROUP(drive)->wrq = *rq; /* scratchpad */
@@ -652,15 +656,13 @@
 	taskfile.device_head	= ((block>>8)&0x0f)|drive->select.all;
 	taskfile.command	= (rq_data_dir(rq)==READ)?PROMISE_READ:PROMISE_WRITE;
 
-	memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
-	memcpy(args.hobRegister, NULL, sizeof(struct hd_drive_hob_hdr));
+	args.taskfile = taskfile;
+	memset(&args.hobfile, 0, sizeof(struct hd_drive_hob_hdr));
+
 	ide_cmd_type_parser(&args);
 	/* We don't use the generic inerrupt handlers here? */
 	args.prehandler		= NULL;
 	args.handler		= NULL;
-	args.rq			= rq;
-	args.block		= block;
-	rq->special		= NULL;
 	rq->special		= &args;
 
 	return do_pdc4030_io(drive, &args);
diff --git a/drivers/ide/pdcadma.c b/drivers/ide/pdcadma.c
index 49fd004..9be4833 100644
--- a/drivers/ide/pdcadma.c
+++ b/drivers/ide/pdcadma.c
@@ -82,12 +82,12 @@
 	return 0;
 }
 
-unsigned int __init ata66_pdcadma (ide_hwif_t *hwif)
+unsigned int __init ata66_pdcadma(struct ata_channel *channel)
 {
 	return 1;
 }
 
-void __init ide_init_pdcadma (ide_hwif_t *hwif)
+void __init ide_init_pdcadma(struct ata_channel *hwif)
 {
 	hwif->autodma = 0;
 	hwif->dma_base = 0;
@@ -101,7 +101,7 @@
 //	}
 }
 
-void __init ide_dmacapable_pdcadma (ide_hwif_t *hwif, unsigned long dmabase)
+void __init ide_dmacapable_pdcadma(struct ata_channel *hwif, unsigned long dmabase)
 {
 //	ide_setup_dma(hwif, dmabase, 8);
 }
diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c
index 384ea0b..8e023e8 100644
--- a/drivers/ide/piix.c
+++ b/drivers/ide/piix.c
@@ -316,7 +316,7 @@
 
 static int piix_set_drive(ide_drive_t *drive, unsigned char speed)
 {
-	ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
+	ide_drive_t *peer = drive->channel->drives + (~drive->dn & 1);
 	struct ata_timing t, p;
 	int err, T, UT, umul;
 
@@ -341,7 +341,7 @@
 				ata_timing_merge(&p, &t, &t, IDE_TIMING_ALL);
 	}
 
-	piix_set_speed(HWIF(drive)->pci_dev, drive->dn, &t, umul);
+	piix_set_speed(drive->channel->pci_dev, drive->dn, &t, umul);
 
 	if (!drive->init_speed)	
 		drive->init_speed = speed;
@@ -357,7 +357,7 @@
 
 static void piix_tune_drive(ide_drive_t *drive, unsigned char pio)
 {
-	if (!((piix_enabled >> HWIF(drive)->channel) & 1))
+	if (!((piix_enabled >> drive->channel->unit) & 1))
 		return;
 
 	if (pio == 255) {
@@ -381,7 +381,7 @@
 
 	if (func == ide_dma_check) {
 
-		short w80 = HWIF(drive)->udma_four;
+		short w80 = drive->channel->udma_four;
 
 		short speed = ata_timing_mode(drive,
 			XFER_PIO | XFER_EPIO | 
@@ -392,7 +392,7 @@
 
 		piix_set_drive(drive, speed);
 
-		func = (HWIF(drive)->autodma && (speed & XFER_MODE) != XFER_PIO)
+		func = (drive->channel->autodma && (speed & XFER_MODE) != XFER_PIO)
 			? ide_dma_on : ide_dma_off_quietly;
 
 	}
@@ -533,12 +533,12 @@
 	return 0;
 }
 
-unsigned int __init ata66_piix(ide_hwif_t *hwif)
+unsigned int __init ata66_piix(struct ata_channel *hwif)
 {
-	return ((piix_enabled & piix_80w) >> hwif->channel) & 1;
+	return ((piix_enabled & piix_80w) >> hwif->unit) & 1;
 }
 
-void __init ide_init_piix(ide_hwif_t *hwif)
+void __init ide_init_piix(struct ata_channel *hwif)
 {
 	int i;
 
@@ -550,7 +550,7 @@
 		hwif->drives[i].io_32bit = 1;
 		hwif->drives[i].unmask = 1;
 		hwif->drives[i].autotune = 1;
-		hwif->drives[i].dn = hwif->channel * 2 + i;
+		hwif->drives[i].dn = hwif->unit * 2 + i;
 	}
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
@@ -570,9 +570,9 @@
  * and only if DMA is safe with the chip and bridge.
  */
 
-void __init ide_dmacapable_piix(ide_hwif_t *hwif, unsigned long dmabase)
+void __init ide_dmacapable_piix(struct ata_channel *hwif, unsigned long dmabase)
 {
-	if (((piix_enabled >> hwif->channel) & 1)
+	if (((piix_enabled >> hwif->unit) & 1)
 		&& !(piix_config->flags & PIIX_NODMA))
 			ide_setup_dma(hwif, dmabase, 8);
 }
diff --git a/drivers/ide/qd65xx.c b/drivers/ide/qd65xx.c
index 609afe5..8f9a2cc 100644
--- a/drivers/ide/qd65xx.c
+++ b/drivers/ide/qd65xx.c
@@ -125,11 +125,11 @@
  * qd6500_compute_timing
  *
  * computes the timing value where
- * 	lower nibble represents active time,   in count of VLB clocks
- * 	upper nibble represents recovery time, in count of VLB clocks
+ *	lower nibble represents active time,   in count of VLB clocks
+ *	upper nibble represents recovery time, in count of VLB clocks
  */
 
-static byte qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recovery_time)
+static byte qd6500_compute_timing(struct ata_channel *hwif, int active_time, int recovery_time)
 {
 	byte active_cycle,recovery_cycle;
 
@@ -208,7 +208,7 @@
 
 static void qd_set_timing (ide_drive_t *drive, byte timing)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 
 	drive->drive_data &= 0xff00;
 	drive->drive_data |= timing;
@@ -240,7 +240,7 @@
 		recovery_time = drive->id->eide_pio - 120;
 	}
 
-	qd_set_timing(drive,qd6500_compute_timing(HWIF(drive),active_time,recovery_time));
+	qd_set_timing(drive,qd6500_compute_timing(drive->channel, active_time,recovery_time));
 }
 
 /*
@@ -250,7 +250,7 @@
 static void qd6580_tune_drive (ide_drive_t *drive, byte pio)
 {
 	struct ata_timing *t;
-	int base = HWIF(drive)->select_data;
+	int base = drive->channel->select_data;
 	int active_time   = 175;
 	int recovery_time = 415; /* worst case values from the dos driver */
 
@@ -291,9 +291,9 @@
 		printk(KERN_INFO "%s: PIO mode%d\n", drive->name, pio - XFER_PIO_0);
 	}
 
-	if (!HWIF(drive)->channel && drive->type != ATA_DISK) {
+	if (!drive->channel->unit && drive->type != ATA_DISK) {
 		qd_write_reg(0x5f,QD_CONTROL_PORT);
-		printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO and post-write buffer on %s.\n",drive->name,HWIF(drive)->name);
+		printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO and post-write buffer on %s.\n",drive->name, drive->channel->name);
 	}
 
 	qd_set_timing(drive,qd6580_compute_timing(active_time,recovery_time));
@@ -348,7 +348,7 @@
 	index = ! (config & QD_CONFIG_IDE_BASEPORT);
 
 	if ((config & 0xf0) == QD_CONFIG_QD6500) {
-		ide_hwif_t *hwif = &ide_hwifs[index];
+		struct ata_channel *hwif = &ide_hwifs[index];
 
 		if (qd_testreg(base)) return 1;		/* bad register */
 
@@ -392,7 +392,7 @@
 			config, control, QD_ID3);
 
 		if (control & QD_CONTR_SEC_DISABLED) {
-			ide_hwif_t *hwif = &ide_hwifs[index];
+			struct ata_channel *hwif = &ide_hwifs[index];
 
 			/* secondary disabled */
 			printk(KERN_INFO "%s: qd6580: single IDE board\n",
@@ -420,7 +420,7 @@
 
 				ide_hwifs[i].chipset = ide_qd65xx;
 				ide_hwifs[i].mate = &ide_hwifs[i^1];
-				ide_hwifs[i].channel = i;
+				ide_hwifs[i].unit = i;
 
 				ide_hwifs[i].select_data = base;
 				ide_hwifs[i].config_data = config | (control <<8);
diff --git a/drivers/ide/rz1000.c b/drivers/ide/rz1000.c
index 644ed60..10caa41 100644
--- a/drivers/ide/rz1000.c
+++ b/drivers/ide/rz1000.c
@@ -28,7 +28,7 @@
 
 #ifdef CONFIG_BLK_DEV_IDEPCI
 
-void __init ide_init_rz1000 (ide_hwif_t *hwif)	/* called from ide-pci.c */
+void __init ide_init_rz1000(struct ata_channel *hwif)	/* called from ide-pci.c */
 {
 	unsigned short reg;
 	struct pci_dev *dev = hwif->pci_dev;
@@ -62,7 +62,7 @@
 		printk("IDE: disabled chipset read-ahead (buggy %s)\n", name);
 	} else {
 		for (h = 0; h < MAX_HWIFS; ++h) {
-			ide_hwif_t *hwif = &ide_hwifs[h];
+			struct ata_channel *hwif = &ide_hwifs[h];
 			if ((hwif->io_ports[IDE_DATA_OFFSET] == 0x1f0 || hwif->io_ports[IDE_DATA_OFFSET] == 0x170)
 			 && (hwif->chipset == ide_unknown || hwif->chipset == ide_generic))
 			{
@@ -71,7 +71,7 @@
 				hwif->drives[0].no_unmask = 1;
 				hwif->drives[1].no_unmask = 1;
 				if (hwif->io_ports[IDE_DATA_OFFSET] == 0x170)
-					hwif->channel = 1;
+					hwif->unit = 1;
 				printk("%s: serialized, disabled unmasking (buggy %s)\n", hwif->name, name);
 			}
 		}
diff --git a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c
index 1e4396c..1760885 100644
--- a/drivers/ide/serverworks.c
+++ b/drivers/ide/serverworks.c
@@ -243,7 +243,7 @@
 	byte dma_modes[]	= { 0x77, 0x21, 0x20 };
 	byte pio_modes[]	= { 0x5d, 0x47, 0x34, 0x22, 0x20 };
 
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 	byte unit		= (drive->select.b.unit & 0x01);
 	byte csb5		= (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) ? 1 : 0;
@@ -255,7 +255,7 @@
 
 	byte drive_pci		= 0x00;
 	byte drive_pci2		= 0x00;
-	byte drive_pci3		= hwif->channel ? 0x57 : 0x56;
+	byte drive_pci3		= hwif->unit ? 0x57 : 0x56;
 
 	byte ultra_enable	= 0x00;
 	byte ultra_timing	= 0x00;
@@ -413,7 +413,7 @@
 static int config_chipset_for_dma (ide_drive_t *drive)
 {
 	struct hd_driveid *id	= drive->id;
-	struct pci_dev *dev	= HWIF(drive)->pci_dev;
+	struct pci_dev *dev	= drive->channel->pci_dev;
 	byte udma_66	= eighty_ninty_three(drive);
 	int ultra66	= (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) ? 1 : 0;
 	int ultra100	= (ultra66 && svwks_revision >= SVWKS_CSB5_REVISION_NEW) ? 1 : 0;
@@ -436,7 +436,7 @@
 	struct hd_driveid *id = drive->id;
 	ide_dma_action_t dma_func = ide_dma_on;
 
-	if (id && (id->capability & 1) && HWIF(drive)->autodma) {
+	if (id && (id->capability & 1) && drive->channel->autodma) {
 		/* Consult the list of known "bad" drives */
 		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
 			dma_func = ide_dma_off;
@@ -477,7 +477,7 @@
 no_dma_set:
 		config_chipset_for_pio(drive);
 	}
-	return HWIF(drive)->dmaproc(dma_func, drive);
+	return drive->channel->dmaproc(dma_func, drive);
 }
 
 static int svwks_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
@@ -487,7 +487,7 @@
 			return config_drive_xfer_rate(drive);
 		case ide_dma_end:
 		{
-			ide_hwif_t *hwif		= HWIF(drive);
+			struct ata_channel *hwif = drive->channel;
 			unsigned long dma_base		= hwif->dma_base;
 	
 			if(inb(dma_base+0x02)&1)
@@ -584,13 +584,13 @@
  * Bit 14 clear = primary IDE channel does not have 80-pin cable.
  * Bit 14 set   = primary IDE channel has 80-pin cable.
  */
-static unsigned int __init ata66_svwks_dell (ide_hwif_t *hwif)
+static unsigned int __init ata66_svwks_dell(struct ata_channel *hwif)
 {
 	struct pci_dev *dev = hwif->pci_dev;
 	if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
 	    dev->vendor	== PCI_VENDOR_ID_SERVERWORKS &&
 	    dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
-		return ((1 << (hwif->channel + 14)) &
+		return ((1 << (hwif->unit + 14)) &
 			dev->subsystem_device) ? 1 : 0;
 	return 0;
 }
@@ -601,18 +601,18 @@
  *
  * WARNING: this only works on Alpine hardware!
  */
-static unsigned int __init ata66_svwks_cobalt (ide_hwif_t *hwif)
+static unsigned int __init ata66_svwks_cobalt(struct ata_channel *hwif)
 {
 	struct pci_dev *dev = hwif->pci_dev;
 	if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN &&
 	    dev->vendor	== PCI_VENDOR_ID_SERVERWORKS &&
 	    dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
-		return ((1 << (hwif->channel + 14)) &
+		return ((1 << (hwif->unit + 14)) &
 			dev->subsystem_device) ? 1 : 0;
 	return 0;
 }
 
-unsigned int __init ata66_svwks (ide_hwif_t *hwif)
+unsigned int __init ata66_svwks(struct ata_channel *hwif)
 {
 	struct pci_dev *dev = hwif->pci_dev;
 
@@ -627,10 +627,10 @@
 	return 0;
 }
 
-void __init ide_init_svwks (ide_hwif_t *hwif)
+void __init ide_init_svwks(struct ata_channel *hwif)
 {
 	if (!hwif->irq)
-		hwif->irq = hwif->channel ? 15 : 14;
+		hwif->irq = hwif->unit ? 15 : 14;
 
 	hwif->tuneproc = &svwks_tune_drive;
 	hwif->speedproc = &svwks_tune_chipset;
diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c
index bf0cf8d..9b45da0 100644
--- a/drivers/ide/sis5513.c
+++ b/drivers/ide/sis5513.c
@@ -434,7 +434,7 @@
 /* Enables per-drive prefetch and postwrite */
 static void config_drive_art_rwp (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 
 	byte reg4bh		= 0;
@@ -460,7 +460,7 @@
 /* Set per-drive active and recovery time */
 static void config_art_rwp_pio (ide_drive_t *drive, byte pio)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 
 	byte			timing, drive_pci, test1, test2;
@@ -560,7 +560,7 @@
 
 static int sis5513_tune_chipset (ide_drive_t *drive, byte speed)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 
 	byte			drive_pci, reg;
@@ -640,12 +640,12 @@
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 /*
- * ((id->hw_config & 0x4000|0x2000) && (HWIF(drive)->udma_four))
+ * ((id->hw_config & 0x4000|0x2000) && (drive->channel->udma_four))
  */
 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 hd_driveid *id = drive->id;
+	struct ata_channel *hwif = drive->channel;
 
 	byte			speed = 0;
 
@@ -700,7 +700,7 @@
 	struct hd_driveid *id		= drive->id;
 	ide_dma_action_t dma_func	= ide_dma_off_quietly;
 
-	if (id && (id->capability & 1) && HWIF(drive)->autodma) {
+	if (id && (id->capability & 1) && drive->channel->autodma) {
 		/* Consult the list of known "bad" drives */
 		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
 			dma_func = ide_dma_off;
@@ -740,7 +740,7 @@
 		(void) config_chipset_for_pio(drive, 5);
 	}
 
-	return HWIF(drive)->dmaproc(dma_func, drive);
+	return drive->channel->dmaproc(dma_func, drive);
 }
 
 /* initiates/aborts (U)DMA read/write operations on a drive. */
@@ -841,10 +841,10 @@
 	return 0;
 }
 
-unsigned int __init ata66_sis5513 (ide_hwif_t *hwif)
+unsigned int __init ata66_sis5513(struct ata_channel *hwif)
 {
 	byte reg48h = 0, ata66 = 0;
-	byte mask = hwif->channel ? 0x20 : 0x10;
+	byte mask = hwif->unit ? 0x20 : 0x10;
 	pci_read_config_byte(hwif->pci_dev, 0x48, &reg48h);
 
 	if (dma_capability >= ATA_66) {
@@ -853,10 +853,10 @@
         return ata66;
 }
 
-void __init ide_init_sis5513 (ide_hwif_t *hwif)
+void __init ide_init_sis5513(struct ata_channel *hwif)
 {
 
-	hwif->irq = hwif->channel ? 15 : 14;
+	hwif->irq = hwif->unit ? 15 : 14;
 
 	hwif->tuneproc = &sis5513_tune_drive;
 	hwif->speedproc = &sis5513_tune_chipset;
diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c
index fd60ffe..158070c 100644
--- a/drivers/ide/sl82c105.c
+++ b/drivers/ide/sl82c105.c
@@ -57,13 +57,13 @@
  */
 static void config_for_pio(ide_drive_t *drive, int pio, int report)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev = hwif->pci_dev;
 	struct ata_timing *t;
 	unsigned short drv_ctrl = 0x909;
 	unsigned int xfer_mode, reg;
 
-	reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0);
+	reg = (hwif->unit ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0);
 
 	if (pio == 255)
 		xfer_mode = ata_timing_mode(drive, XFER_PIO | XFER_EPIO);
@@ -95,12 +95,12 @@
  */
 static int config_for_dma(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev = hwif->pci_dev;
 	unsigned short drv_ctrl = 0x909;
 	unsigned int reg;
 
-	reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0);
+	reg = (hwif->unit ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0);
 
 	if (ide_config_drive_speed(drive, XFER_MW_DMA_2) == 0)
 		drv_ctrl = 0x0240;
@@ -120,7 +120,7 @@
 
 	do {
 		struct hd_driveid *id = drive->id;
-		ide_hwif_t *hwif = HWIF(drive);
+		struct ata_channel *hwif = drive->channel;
 
 		if (!hwif->autodma)
 			break;
@@ -146,7 +146,7 @@
 		}
 	} while (0);
 
-	return HWIF(drive)->dmaproc(dma_func, drive);
+	return drive->channel->dmaproc(dma_func, drive);
 }
 
 /*
@@ -232,7 +232,7 @@
 	return dev->irq;
 }
 
-void __init dma_init_sl82c105(ide_hwif_t *hwif, unsigned long dma_base)
+void __init dma_init_sl82c105(struct ata_channel *hwif, unsigned long dma_base)
 {
 	unsigned int rev;
 	byte dma_state;
@@ -261,7 +261,7 @@
 /*
  * Initialise the chip
  */
-void __init ide_init_sl82c105(ide_hwif_t *hwif)
+void __init ide_init_sl82c105(struct ata_channel *hwif)
 {
 	hwif->tuneproc = tune_sl82c105;
 }
diff --git a/drivers/ide/trm290.c b/drivers/ide/trm290.c
index 70dffe8..50675cf 100644
--- a/drivers/ide/trm290.c
+++ b/drivers/ide/trm290.c
@@ -141,7 +141,7 @@
 
 static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	unsigned int reg;
 	unsigned long flags;
 
@@ -153,14 +153,14 @@
 
 	if (reg != hwif->select_data) {
 		hwif->select_data = reg;
-		outb(0x51|(hwif->channel<<3), hwif->config_data+1);	/* set PIO/DMA */
+		outb(0x51|(hwif->unit<<3), hwif->config_data+1);	/* set PIO/DMA */
 		outw(reg & 0xff, hwif->config_data);
 	}
 
 	/* enable IRQ if not probing */
 	if (drive->present) {
 		reg = inw(hwif->config_data+3) & 0x13;
-		reg &= ~(1 << hwif->channel);
+		reg &= ~(1 << hwif->unit);
 		outw(reg, hwif->config_data+3);
 	}
 
@@ -175,7 +175,7 @@
 #ifdef CONFIG_BLK_DEV_IDEDMA
 static int trm290_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	unsigned int count, reading = 2, writing = 0;
 
 	switch (func) {
@@ -194,6 +194,7 @@
 			outw((count * 2) - 1, hwif->dma_base+2); /* start DMA */
 			if (drive->type != ATA_DISK)
 				return 0;
+			BUG_ON(HWGROUP(drive)->handler);
 			ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);
 			OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
 			return 0;
@@ -216,7 +217,7 @@
 /*
  * Invoked from ide-dma.c at boot time.
  */
-void __init ide_init_trm290 (ide_hwif_t *hwif)
+void __init ide_init_trm290(struct ata_channel *hwif)
 {
 	unsigned int cfgbase = 0;
 	unsigned long flags;
@@ -237,7 +238,7 @@
 	__save_flags(flags);	/* local CPU only */
 	__cli();		/* local CPU only */
 	/* put config reg into first byte of hwif->select_data */
-	outb(0x51|(hwif->channel<<3), hwif->config_data+1);
+	outb(0x51|(hwif->unit<<3), hwif->config_data+1);
 	hwif->select_data = 0x21;			/* select PIO as default */
 	outb(hwif->select_data, hwif->config_data);
 	reg = inb(hwif->config_data+3);			/* get IRQ info */
@@ -246,10 +247,10 @@
 	__restore_flags(flags);	/* local CPU only */
 
 	if ((reg & 0x10))
-		hwif->irq = hwif->channel ? 15 : 14;	/* legacy mode */
+		hwif->irq = hwif->unit ? 15 : 14;	/* legacy mode */
 	else if (!hwif->irq && hwif->mate && hwif->mate->irq)
 		hwif->irq = hwif->mate->irq;		/* sharing IRQ with mate */
-	ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3);
+	ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->unit ? 0x0080 : 0x0000), 3);
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	hwif->dmaproc = &trm290_dmaproc;
@@ -264,10 +265,10 @@
 		 * for the control basereg, so this kludge ensures that we use only
 		 * values that are known to work.  Ugh.		-ml
 		 */
-		unsigned short old, compat = hwif->channel ? 0x374 : 0x3f4;
+		unsigned short old, compat = hwif->unit ? 0x374 : 0x3f4;
 		static unsigned short next_offset = 0;
 
-		outb(0x54|(hwif->channel<<3), hwif->config_data+1);
+		outb(0x54|(hwif->unit<<3), hwif->config_data+1);
 		old = inw(hwif->config_data) & ~1;
 		if (old != compat && inb(old+2) == 0xff) {
 			compat += (next_offset += 0x400);	/* leave lower 10 bits untouched */
diff --git a/drivers/ide/umc8672.c b/drivers/ide/umc8672.c
index 8f9d982..bb70bc7 100644
--- a/drivers/ide/umc8672.c
+++ b/drivers/ide/umc8672.c
@@ -111,7 +111,7 @@
 static void tune_umc (ide_drive_t *drive, byte pio)
 {
 	unsigned long flags;
-	ide_hwgroup_t *hwgroup = ide_hwifs[HWIF(drive)->index^1].hwgroup;
+	ide_hwgroup_t *hwgroup = ide_hwifs[drive->channel->index ^ 1].hwgroup;
 
 	if (pio == 255)
 		pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0;
@@ -160,5 +160,5 @@
 	ide_hwifs[1].tuneproc = &tune_umc;
 	ide_hwifs[0].mate = &ide_hwifs[1];
 	ide_hwifs[1].mate = &ide_hwifs[0];
-	ide_hwifs[1].channel = 1;
+	ide_hwifs[1].unit = 1;
 }
diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c
index 38eb933..d750057 100644
--- a/drivers/ide/via82cxxx.c
+++ b/drivers/ide/via82cxxx.c
@@ -302,7 +302,7 @@
 
 static int via_set_drive(ide_drive_t *drive, unsigned char speed)
 {
-	ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
+	ide_drive_t *peer = drive->channel->drives + (~drive->dn & 1);
 	struct ata_timing t, p;
 	unsigned int T, UT;
 
@@ -328,7 +328,7 @@
 		ata_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
 	}
 
-	via_set_speed(HWIF(drive)->pci_dev, drive->dn, &t);
+	via_set_speed(drive->channel->pci_dev, drive->dn, &t);
 
 	if (!drive->init_speed)
 		drive->init_speed = speed;
@@ -344,7 +344,7 @@
 
 static void via82cxxx_tune_drive(ide_drive_t *drive, unsigned char pio)
 {
-	if (!((via_enabled >> HWIF(drive)->channel) & 1))
+	if (!((via_enabled >> drive->channel->unit) & 1))
 		return;
 
 	if (pio == 255) {
@@ -368,7 +368,7 @@
 
 	if (func == ide_dma_check) {
 
-		short w80 = HWIF(drive)->udma_four;
+		short w80 = drive->channel->udma_four;
 
 		short speed = ata_timing_mode(drive,
 			XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA |
@@ -379,7 +379,7 @@
 
 		via_set_drive(drive, speed);
 
-		func = (HWIF(drive)->autodma && (speed & XFER_MODE) != XFER_PIO)
+		func = (drive->channel->autodma && (speed & XFER_MODE) != XFER_PIO)
 			? ide_dma_on : ide_dma_off_quietly;
 	}
 
@@ -523,12 +523,12 @@
 	return 0;
 }
 
-unsigned int __init ata66_via82cxxx(ide_hwif_t *hwif)
+unsigned int __init ata66_via82cxxx(struct ata_channel *hwif)
 {
-	return ((via_enabled & via_80w) >> hwif->channel) & 1;
+	return ((via_enabled & via_80w) >> hwif->unit) & 1;
 }
 
-void __init ide_init_via82cxxx(ide_hwif_t *hwif)
+void __init ide_init_via82cxxx(struct ata_channel *hwif)
 {
 	int i;
 
@@ -540,7 +540,7 @@
 		hwif->drives[i].io_32bit = 1;
 		hwif->drives[i].unmask = (via_config->flags & VIA_NO_UNMASK) ? 0 : 1;
 		hwif->drives[i].autotune = 1;
-		hwif->drives[i].dn = hwif->channel * 2 + i;
+		hwif->drives[i].dn = hwif->unit * 2 + i;
 	}
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
@@ -559,8 +559,8 @@
  * We allow the BM-DMA driver to only work on enabled interfaces.
  */
 
-void __init ide_dmacapable_via82cxxx(ide_hwif_t *hwif, unsigned long dmabase)
+void __init ide_dmacapable_via82cxxx(struct ata_channel *hwif, unsigned long dmabase)
 {
-	if ((via_enabled >> hwif->channel) & 1)
+	if ((via_enabled >> hwif->unit) & 1)
 		ide_setup_dma(hwif, dmabase, 8);
 }
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index 0a763bc..9055970 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -100,7 +100,6 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <linux/sched.h>
-#include <asm/segment.h>
 #include <linux/types.h>
 #include <linux/wrapper.h>
 #include <linux/vmalloc.h>
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index 6194e0c..5519f51 100644
--- a/drivers/